Sai*_*int 3 .net design-patterns dependency-injection strategy-pattern autofac
我想加入使用策略模式和 DI。
class A : IBase
{
public void Do();
}
class B : IBase
{
public void Do();
}
interface IBase
{
void Do();
}
class Context()
{
private _usedClass;
void SetClass(IBase usedClass)
{
_usedClass = usedClass;
}
public void Do()
{
_usedClass.Do();
}
}
void Main()
{
var context = new Context();
var someEnum = SomeMethod();
//how to use here DI resolve to get appropriate class instead of if/else?
if (someEnum == MyEnum.A)
context.SetClass(new A());
else if (someEnum == MyEnum.B)
context.SetClass(new B());
context.Do();
}
Run Code Online (Sandbox Code Playgroud)
如何在这里使用 DI 解析来获得适当的类而不是 if/else?谢谢
我肯定会使用委托工厂来避免对 IoC 容器本身的依赖。通过使用 Keyed Service Lookup,您的代码/工厂将与 Autofac 紧密耦合。
这是一个漂亮而干净的示例,不依赖于 Autofac:
策略:
public interface IStrategy { void Do(); }
public class ConcreteStrategyA : IStrategy { public void Do() { Console.WriteLine("Called ConcreteStrategyA.Do()"); } };
public class ConcreteStrategyB : IStrategy { public void Do() { Console.WriteLine("Called ConcreteStrategyB.Do()"); } };
Run Code Online (Sandbox Code Playgroud)
您要打开的枚举:
public enum ESomeEnum
{
UseStrategyA,
UseStrategyB,
}
Run Code Online (Sandbox Code Playgroud)
使用策略的上下文:
private readonly Func<ESomeEnum, IStrategy> _strategyFactory;
public Context(Func<ESomeEnum, IStrategy> strategyFactory)
{
_strategyFactory = strategyFactory;
}
public void DoSomething()
{
_strategyFactory(ESomeEnum.UseStrategyB).Do();
_strategyFactory(ESomeEnum.UseStrategyA).Do();
}
Run Code Online (Sandbox Code Playgroud)
最后是容器配置:
var builder = new ContainerBuilder();
builder.RegisterType<Context>().AsSelf().SingleInstance();
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(IStrategy)))
.Where(t => typeof(IStrategy).IsAssignableFrom(t))
.AsSelf();
builder.Register<Func<ESomeEnum, IStrategy>>(c =>
{
var cc = c.Resolve<IComponentContext>();
return (someEnum) =>
{
switch (someEnum)
{
case ESomeEnum.UseStrategyA:
return cc.Resolve<ConcreteStrategyA>();
case ESomeEnum.UseStrategyB:
return cc.Resolve<ConcreteStrategyB>();
default:
throw new ArgumentException();
}
};
});
var container = builder.Build();
container.Resolve<Context>().DoSomething();
Run Code Online (Sandbox Code Playgroud)
如果这些策略不消耗在您的容器中注册的任何依赖项,您可以自己新建它们,并像这样简化您的配置:
var builder = new ContainerBuilder();
builder.RegisterType<Context>().AsSelf().SingleInstance();
builder.Register<Func<ESomeEnum, IStrategy>>(c => StrategyFactory.GetStrategy);
var container = builder.Build();
container.Resolve<Context>().DoSomething();
Run Code Online (Sandbox Code Playgroud)
并将开关盒放在一个单独的类中:
public static class StrategyFactory
{
internal static IStrategy GetStrategy(ESomeEnum someEnum)
{
switch (someEnum)
{
case ESomeEnum.UseStrategyA:
return new ConcreteStrategyA();
case ESomeEnum.UseStrategyB:
return new ConcreteStrategyB();
default:
throw new ArgumentException();
}
}
}
Run Code Online (Sandbox Code Playgroud)
完整运行代码示例 -签入.NET Fiddle:
using Autofac;
using System;
using System.Reflection;
namespace Samples.Autofac.StrategyPattern
{
public interface IStrategy { void Do(); }
public class ConcreteStrategyA : IStrategy { public void Do() { Console.WriteLine("Called ConcreteStrategyA.Do()"); } };
public class ConcreteStrategyB : IStrategy { public void Do() { Console.WriteLine("Called ConcreteStrategyB.Do()"); } };
public enum ESomeEnum
{
UseStrategyA, UseStrategyB,
}
public class Context
{
private readonly Func<ESomeEnum, IStrategy> _strategyFactory;
public Context(Func<ESomeEnum, IStrategy> strategyFactory)
{
_strategyFactory = strategyFactory;
}
public void DoSomething()
{
_strategyFactory(ESomeEnum.UseStrategyB).Do();
_strategyFactory(ESomeEnum.UseStrategyA).Do();
}
}
public class AutofacExample
{
public static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<Context>().AsSelf().SingleInstance();
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(IStrategy)))
.Where(t => typeof(IStrategy).IsAssignableFrom(t))
.AsSelf();
builder.Register<Func<ESomeEnum, IStrategy>>(c =>
{
var cc = c.Resolve<IComponentContext>();
return (someEnum) =>
{
switch (someEnum)
{
case ESomeEnum.UseStrategyA:
return cc.Resolve<ConcreteStrategyA>();
case ESomeEnum.UseStrategyB:
return cc.Resolve<ConcreteStrategyB>();
default:
throw new ArgumentException();
}
};
});
var container = builder.Build();
container.Resolve<Context>().DoSomething();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4222 次 |
| 最近记录: |