C#-Ninject,IoC和工厂模式 [英] C# - Ninject, IoC and factory pattern

查看:106
本文介绍了C#-Ninject,IoC和工厂模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个控制台应用程序,需要根据用户输入执行某些功能.如果用户输入功能1"->我执行功能1,依此类推.

我正在尝试尽可能简洁,通用地编写该项目,并且我想使用 IoC SOLID 概念,这有点困扰. /p>

我到目前为止所拥有的:

public interface IFeature
{
    String execFeature();
}

interface IFeatureFactory
{
    IFeature createFeature(String input);
}

我首先想到的是在具体工厂类上放置一个开关盒,以了解来自用户的输入,并创建具体的功能 >因此,但我敢打赌,使用 IoC 可以找到一种更好的方法.

我阅读了有关Ninject工厂扩展的信息,但不了解如何在我的项目中使用它.

使用IoC/Ninject进行工厂模式的最佳方法是什么?

解决方案

如果您的IFeature实现不具有其他依赖关系,而使用方法则很好且非常简单.
例如,假设您有2个IFeature实现-SomeFeature和OtherFeature都具有无参数构造函数.
您建议的工厂实现将是这样的:

public class FeatureFactory: IFeatureFactory
{
    IFeature CreateFeature(string input)
    {
         if(input=="SomeFeature")
         {
           return new SomeFeature();
         }
         else
         {
           return new OtherFeature ();
         }
    }
}

但是,当您的IFeature实现使用这种方法具有自己的依赖关系时,就会失去使用Ninject和IoC的意义.
例如,假设说SomeFeature看起来像这样:

public class SomeFeature : IFeature
{
    private readonly IDependency1 _dependency1;
    private readonly IDependency2 _dependency2; 

    public SomeFeature (IDependency1 dependency1, IDependency2 dependency2)
    {
        _dependency1=dependency1;
        _dependency2=dependency2;
    }

    string execFeature()
    {
      //Some code here...
    }
}

与OtherFeature相似...

 public class OtherFeature: IFeature
    {
        private readonly IDependency1 _dependency1;
        private readonly IDependency2 _dependency2; 

        public OtherFeature(IDependency1 dependency1, IDependency2 dependency2)
        {
            _dependency1=dependency1;
            _dependency2=dependency2;
        }

        string execFeature()
        {
          //Some code here...
        }
    }

现在您的工厂将变成这样:

 public class FeatureFactory: IFeatureFactory 
    {
        IFeature CreateFeature(string input)
        {
             if(input=="SomeFeature")
             {
               return new SomeFeature(new Dependency1Implementation(), new Dependency2Implementation());
             }
             else
             {
               return new OtherFeature(new Dependency1Implementation(), new Dependency2Implementation());
             }
        }
    }

在这里可以使用ninject.extensions.factory的功能 通过使用容器为您解决此依赖关系(此依赖关系可以具有自己的依赖关系,并且很快就会变得混乱).
如前所述,您可以使用命名绑定来绑定每个IFeature实现.

Bind<IFeature>().To<SomeFeature>().Named("SomeFeature");
Bind<IFeature>().To<OtherFeature>().Named("OtherFeature");

当然,您还应该绑定其他依赖项

Bind<IDependency1>().To<Dependency1Implementation>();
Bind<IDependency2>().To<Dependency2Implementation>();

然后使用工厂扩展名将IFeatureFactory绑定到Factory.

Bind<IFeatureFactory>().ToFactory();

您要做的是在IFeatureFactory中为每个IFeature实现创建工厂方法,并根据名为binding的功能将其称为Get....

public interface IFeatureFactory
{
  IFeature GetSomeFeature();
  IFeature GetOtherFeature();
}

现在ninject将为您实现该类,并知道为每种方法选择哪种实现.(不需要服务定位器.)
您可以在客户端的输入上使用switch语句来选择要调用的工厂方法,也可以将其包装在其中将包含switch语句的某些提供程序类中,在两种情况下,您都不必执行"new"操作IFeature自己实现.
当然,如果需要和其他更复杂的事情,您可以通过工厂方法将参数传递给实现的构造函数.

我建议您阅读以获得更多信息.

修改
我想强调一下,您不必为每个实现编写工厂方法,您可以对所有方法使用相同的方法(可能,但是更复杂).
为此,您需要创建自定义实例提供程序要检测要实例化的实现(例如,根据工厂参数),请在上面的链接和 I execute Feature 1, and so on.

I am trying to write this project as clean and as generic as possible, and I want to use the IoC and SOLID concepts, and i am kinda stuck.

What I have so far:

public interface IFeature
{
    String execFeature();
}

and

interface IFeatureFactory
{
    IFeature createFeature(String input);
}

My first thought was just to have a switch case on the concrete Factory class about the input from the user, and create the concrete Feature accordingly, but I bet there is a better way to do it with IoC.

I read about Ninject factory extension, but didn't understand how to use it in my project.

Whatis the best way to do the factory pattern with IoC/Ninject?

解决方案

If your IFeature implementations does not have other dependencies than using your approach is fine and very simple.
For example lets say you have 2 implementations of IFeature - SomeFeature and OtherFeature that both have parametersless constructor.
Your factory implementation as you suggest would be something like that:

public class FeatureFactory: IFeatureFactory
{
    IFeature CreateFeature(string input)
    {
         if(input=="SomeFeature")
         {
           return new SomeFeature();
         }
         else
         {
           return new OtherFeature ();
         }
    }
}

However when your IFeature implementations have their own dependencies using this approach you lose the point of using Ninject and IoC.
For example lets say That SomeFeature looks something like that:

public class SomeFeature : IFeature
{
    private readonly IDependency1 _dependency1;
    private readonly IDependency2 _dependency2; 

    public SomeFeature (IDependency1 dependency1, IDependency2 dependency2)
    {
        _dependency1=dependency1;
        _dependency2=dependency2;
    }

    string execFeature()
    {
      //Some code here...
    }
}

And OtherFeature is similar...

 public class OtherFeature: IFeature
    {
        private readonly IDependency1 _dependency1;
        private readonly IDependency2 _dependency2; 

        public OtherFeature(IDependency1 dependency1, IDependency2 dependency2)
        {
            _dependency1=dependency1;
            _dependency2=dependency2;
        }

        string execFeature()
        {
          //Some code here...
        }
    }

Now your factory would become something like that:

 public class FeatureFactory: IFeatureFactory 
    {
        IFeature CreateFeature(string input)
        {
             if(input=="SomeFeature")
             {
               return new SomeFeature(new Dependency1Implementation(), new Dependency2Implementation());
             }
             else
             {
               return new OtherFeature(new Dependency1Implementation(), new Dependency2Implementation());
             }
        }
    }

This is the place when you can use the power of the ninject.extensions.factory by using the container to solve this dependencies for you.(This dependencies can have their own dependencies and it can get messy very quickly).
As other mentioned you can bind every IFeature implementation using named binding.

Bind<IFeature>().To<SomeFeature>().Named("SomeFeature");
Bind<IFeature>().To<OtherFeature>().Named("OtherFeature");

Of Course you should bind other dependencies as well

Bind<IDependency1>().To<Dependency1Implementation>();
Bind<IDependency2>().To<Dependency2Implementation>();

And then bind the IFeatureFactory to Factory using the factory extension.

Bind<IFeatureFactory>().ToFactory();

What you have to do is create factory method for each of your IFeature implementations in IFeatureFactory and call it Get... according to the Feature named binding.

public interface IFeatureFactory
{
  IFeature GetSomeFeature();
  IFeature GetOtherFeature();
}

Now ninject will implement(!) this class for you and know which implementation to choose for each method.(There is no need for service locator....)
You can use switch statement over the input in your client to choose which factory method to call or you can wrap it in some provider class that will have the switch statement in it, in both cases you will not have to do the 'new' for IFeature implementations yourself.
Of Course you can pass parameters to the implementations constructors by the factory methods if you need to and other more complex things.

I suggest you to read
this for further information.

Edit
I would like to emphasis you don't have to write factory method for each implementation, you can use the same method for all (It is possible but more complex).
To do it you will need to create custom instance provider to detect which implementation to instantiate (according to the factory parameters for example), more about this in the link above and here.

这篇关于C#-Ninject,IoC和工厂模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆