微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

autofac / c#:特定基类的通用工厂?

autofac是否可以创建只能解析特定基类类型的通用工厂?

我现在看到改造一个brownfield’c#项目使用autofac是多么可行.该项目需要创建一个不同类型但具有相同基类的组件树.这些组件需要身份验证和数据库服务(以及其他内容),因此很难只拥有空构造函数.

因此,工厂可以创建导出基类的对象,使用autofac扫描这些类,并为它们提供工厂.我认为如果你不必为每个类提供工厂,它可能会更容易构建组件对象树.

除此之外,还是这是一个糟糕设计的标志?组件和树应该尽可能少地执行,我们将此树传递给其他服务以提供处理和呈现吗?

像(哪里?是神秘工厂)的东西

public MyBase { 
    public Add(MyBase x) {..}
}

public DerivedA: MyBase {}

public DerivedB : MyBase {}

public DerivedC : DerivedA {}

public SomethingElse
{
     private ? _myBaseFact;

     public SomethingElse(? myBaseFact) { 
            _myBaseFact = myBaseFact;
     }

     public BuildComponentTree() {
        DerivedA a = _myBaseFact<DerivedA>();
        DerivedB b = _myBaseFact<DerivedB>();
        DerivedC c = _myBaseFact<DerivedC>();
        a.Add(b);
        b.Add(c);
     }
}

编辑:我被要求一个更具体的例子,这是公平的:)有框架组件,我想允许开发人员创建自己的组件,而无需注册autofac.拥有工厂类意味着开发人员必须将自定义组件添加到此工厂吗?请原谅这个例子,这与我遇到它时框架的工作原理类似.

FwComponent {
    public FwComponent (DataProvider,AuthManager,OtherModule)
    public Add(FwComponent x);
    public Setup();
    public Process();
    public Render();
}

Page : FwComponent {
    public Page(DataProvider,OtherModule): base(..)
    public string Title;
    ...
}

Input: FwComponent {
    public Input(DataProvider,OtherModule): base(..)
    public string Name;
    public int length;
    ...
}

Button: FwComponent {
    public Button(DataProvider,OtherModule): base(..)
    public string Name;
    ...
}

----

MyCustomButton : Button {
     public MyCustomButton(DataProvider,OtherModule): base(..)
}

MyPersonalPage : FwComponent {

    IContext _container;

    public MyPersonalPage(DataProvider,OtherModule,IContext container): base(..)

    public Setup() {
         var input = _container.Resolve<Input>();
         input.Name = 'xxx';
         input.length = 10;
         Add(input);

         var butt = _container.Resolve<MyCustomButton>();
         butt.name = "xxx";
         Add(butt);    
    }

    public Process() {
        DataProvider.DoStuff();
    }
}

解决方法

在您提供的代码示例中,您似乎使用_myBaseFact< DerivedA>()和_myBaseFact< DerivedB>()请求特定类型.很难看出你想要完成什么,但这对我来说似乎是一种代码味道,因为你仍然依赖于具体的类型.

在我看来,你有两个选择:你注入一个工厂并抽象出派生类型,或者你直接将派生类型注入构造函数.使用工厂在两个场景中很有用:

1:您有某种(不是基于类型的)参数,允许工厂识别返回的类型,如以下示例所示:

public class MyBaseFactory : IMyBaseFactory
{
    public MyBase CreateMyBase(IUserContext user)
    {
        // Create a MyBase based on a user object.
    }
}

2:您的工厂有多种工厂方法

public class MyBaseFactory : IMyBaseFactory
{
    private Autofac.IContainer container;

    public MyBase CreateMyBaseForScenarioA()
    {
        return container.Resolve<DerivedA>();
    }

    public MyBase CreateMyBaseForScenarioB()
    {
        return container.Resolve<DerivedB>();
    }
}

请注意,两个工厂方法都返回MyBase,而不是特定类型.关于多态的整个想法是你不应该关心具体类型.

IMO无论Autofac是否可以为您创建工厂都无关紧要.您不应该依赖于类似于框架的结构,而是依赖于良好的应用程序设计.如果您采用工厂方法,请为该工厂定义接口并根据该接口注入实例.这使得设计非常干净,并且非常好地传达了它的意图.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐