简体   繁体   English

使用 Autofac 创建具有依赖项的类的实例

[英]Create instance of a class with dependencies using Autofac

Problem:问题:

Assume the class:假设类:

public class MyAwesomeClass
{
   private IDependCls _dependCls;
   public MyAwesomeClass(IDependCls dependCls)
   {
       _dependCls = dependCls;
   }

}

And somewhere else I need to get an instance of that class, like so:在其他地方,我需要获取该类的实例,如下所示:

public class SomewhereElse
{
    public void AwesomeMethod()
    {
        //...
        // AwesomeStuff
        //...

        var GetErDone = new MyAwesomeClass();  // PROBLEM! No constructor with 0 arguements
    }
}

Question is, do I问题是,我

Proposed solution 1:建议的解决方案 1:

A) have to make an extra constuctor that resolves the dependency? A)必须制作一个额外的构造函数来解决依赖关系? For example:例如:

   public MyAwesomeClass() // new constructor
   {
       _dependCls = DependencyResolver.Current.GetService<IDependCls>();
   }


public class SomewhereElse
{
    public void AwesomeMethod()
    {
        var GetErDone = new MyAwesomeClass();  // IT WORKS!!
    }
}

Proposed solution 2:建议的解决方案 2:

B) use the resolver inside AwesomeMethod right before var GetErDone B) 在var GetErDone之前使用AwesomeMethod的解析器

public class SomewhereElse
{
    public void AwesomeMethod()
    {
        var depCls = _dependCls = DependencyResolver.Current.GetService<IDependCls>();
        var GetErDone = new MyAwesomeClass(depCls);  // IT WORKS!!
    }
}

Autofac solution? Autofac解决方案?

C) Some other Autofac way? C)其他一些Autofac方式?

Looking for best practices, as well as a good Autofac solution if possible.如果可能的话,寻找最佳实践以及良好的 Autofac 解决方案。 I think the first way is the worst as optional dependancies could lead to a lot of clutter.我认为第一种方法是最糟糕的,因为可选的依赖会导致很多混乱。

Summary:概括:

How do I get a new MyAwesomeClass() when MyAwesomeClass has dependencies?MyAwesomeClass具有依赖项时,如何获得new MyAwesomeClass()

Have a look at the Composition Root pattern.看看组合根模式。

You are right, pulling up the dependency resolution only moves the problem to another place.你是对的,拉起依赖解决方案只会把问题移到另一个地方。 If you continue to move it upwards in your object graph, though, you will reach the entry point of your application.但是,如果您继续在对象图中向上移动它,您将到达应用程序的入口点。 There you will compose your object graph.在那里你将组成你的对象图。

Compare that to the Service Locator anti-pattern (using DependencyResolver in client classes in your case) and you will see that Composition Root is a superior solution.将其与Service Locator 反模式(在您的案例中在客户端类中使用 DependencyResolver)进行比较,您将看到 Composition Root 是一个卓越的解决方案。

First of all apart from constructor injection you can also use property injection and method injection .首先,除了构造函数注入之外,您还可以使用属性注入方法注入 However constructor injection is most common and the fastest method so I suggest to stick to it.然而构造函数注入是最常见和最快的方法,所以我建议坚持使用它。

The second thing you need to do is to register your MyAwesomeClass in the Autofac container along with its dependency, they have some nice examples right at their home page.您需要做的第二件事是在 Autofac 容器中注册您的MyAwesomeClass及其依赖项,他们的主页上有一些很好的示例

And the last thing - you should not create instances of MyAwesomeClass directly - use Autofac instead.最后一件事——你不应该直接创建MyAwesomeClass实例——而是使用 Autofac。 Here is an updated example:这是一个更新的示例:

public void AwesomeMethod()
{
    //...
    // AwesomeStuff
    //...

    var GetErDone = DependencyResolver.Current.GetService<MyAwesomeClass>();
}

If you want to resolve instance automatically via Autofac, you can only choose from this如果你想通过 Autofac 自动解析实例,你只能从这里选择

  • Inject in constructor of your class注入你的类的构造函数
  • Inject in property, by using通过使用注入属性

    var builder = new ContainerBuilder();

    builder.RegisterType<Foo>().PropertiesAutowired();

  • Use global access by DependencyResolver.Current.GetService<IFoo>();通过DependencyResolver.Current.GetService<IFoo>();使用全局访问DependencyResolver.Current.GetService<IFoo>();

In the class containing MyAwesomeMethod take MyAwesomeClass as a constructor dependency.在包含MyAwesomeMethod的类中,将MyAwesomeClass作为构造函数依赖项。 Autofac will take care of the instantiation. Autofac 将负责实例化。

I know that this question is old, but I found a quite useful link on the autofac documentation describing dynamic instantiation of classes.我知道这个问题很老,但我在 autofac 文档中找到了一个非常有用的链接,描述了类的动态实例化。

Autofac Dynamic Instantiation Autofac 动态实例化

Perhaps it could be helpful for someone.也许它可能对某人有帮助。

You can create a new instance of 'MyAwesomeClass' with reflection, resolving the constructor parameters with Autofac.您可以使用反射创建“MyAwesomeClass”的新实例,使用 Autofac 解析构造函数参数。

    public static T Instance<T>() where T : class
    {
        Type instanceType = typeof(T);
        ConstructorInfo constructorInfo = instanceType.GetConstructors()[0];
        ParameterInfo[] constructorParamsInfo = constructorInfo.GetParameters();
        object[] constructorParams = new object[constructorParamsInfo.Length];

        for (int i = 0; i < constructorParamsInfo.Length; i++)
        {
            var parameterInfo = constructorParamsInfo[i];
            var type = parameterInfo.ParameterType;
            constructorParams[i] = Container.Resolve(type);
        }

        object instance = Activator.CreateInstance(instanceType, constructorParams);

        return (T)instance;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM