我正在研究WPF应用程序。
我使用StructureMap来注入依赖项
存在一些服务层类,它们从构造函数中提供参数
我传递给构造函数的值将改变运行时。
表示层的类使用服务为用户呈现数据。每当值发生变化时,我再次使用新值注入服务。但表示层的活动实例返回先前的值。
我已准备好简单的例子以便更好地理解。
// static class that keeps some value
public class ValueKeeper
{
public static string Value { get; set; }
}
public interface IService
{
string Value { get; set; }
}
// Service layer class
public class Service : IService
{
// default constructor
public Service(string value)
{
Value = value;
}
#region IService Members
public string Value { get; set; }
#endregion
}
public class Program
{
private readonly IService _service;
//injecting service class
public Program(IService service)
{
_service = service;
}
// structuremap configuration
private static void Config()
{
ObjectFactory.Initialize(x => x.Scan(scanner =>
{
scanner.TheCallingAssembly();
scanner.WithDefaultConventions();
x.For<IService>().CacheBy(InstanceScope.Hybrid).Use(() =>
{
var service = new Service("value1");
return service;
});
}));
}
// structuremap configuration after value changed.
private static void ReConfig()
{
ObjectFactory.Configure(x => x.Scan(scanner =>
{
x.For<IService>().CacheBy(InstanceScope.Hybrid).Use(() =>
{
var service =new Service(ValueKeeper.Value);
return service;
});
}));
}
private string PresentationMethod()
{
return _service.Value;
}
private static void Main(string[] args)
{
Config(); // Firtst time injecting dependencies
var prog = ObjectFactory.GetInstance<Program>();
Console.WriteLine(prog.PresentationMethod()); // returns "value1"
ValueKeeper.Value = "value 2"; //changing static property
ReConfig(); // reconfig service class with new property
Console.WriteLine(prog.PresentationMethod()); // it returns value1 but I expect value2 .
Console.ReadKey();
}
}
Real应用程序包含许多演示和服务类。
如何使用新对象和值更改实时服务实例?
更新:
我看到了this链接。似乎通过使用Setter Injection,可以更改现有对象。
setter注射我的解决方案吗?
答案 0 :(得分:0)
您可以使用strategy pattern在运行时轻松跟踪和切换同一接口的实例。这是一个简单的例子:
var container = new Container(x => x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.AddAllTypesOf<IDiscountCalculator>();
}));
var strategy = container.GetInstance<IDiscountStrategy>();
Console.WriteLine(strategy.GetDiscount("Regular", 10)); // 0
Console.WriteLine(strategy.GetDiscount("Normal", 10)); // 1
Console.WriteLine(strategy.GetDiscount("Special", 10)); // 5
取决于以下类型:
public interface IDiscountStrategy
{
decimal GetDiscount(string userType, decimal orderTotal);
}
public class DiscountStrategy : IDiscountStrategy
{
private readonly IDiscountCalculator[] _discountCalculators;
public DiscountStrategy(IDiscountCalculator[] discountCalculators)
{
_discountCalculators = discountCalculators;
}
public decimal GetDiscount(string userType, decimal orderTotal)
{
var calculator = _discountCalculators.FirstOrDefault(x => x.AppliesTo(userType));
if (calculator == null) return 0;
return calculator.CalculateDiscount(orderTotal);
}
}
public interface IDiscountCalculator
{
bool AppliesTo(string userType);
decimal CalculateDiscount(decimal orderTotal);
}
public class NormalUserDiscountCalculator : IDiscountCalculator
{
public bool AppliesTo(string userType)
{
return userType == "Normal";
}
public decimal CalculateDiscount(decimal orderTotal)
{
return orderTotal * 0.1m;
}
}
public class SpecialUserDiscountCalculator : IDiscountCalculator
{
public bool AppliesTo(string userType)
{
return userType == "Special";
}
public decimal CalculateDiscount(decimal orderTotal)
{
return orderTotal * 0.5m;
}
}
或者,如果你想要立即处理的短期依赖项,你应该注入一个abstract factory来按需创建它们。
public ISomeObjectFactory
{
ISomeObject Create();
void Release(ISomeObject someObject);
}
public class SomeObjectFactory
: ISomeObjectFactory
{
//private readonly IAclModule aclModule;
// Inject dependencies at application startup here
//public SiteMapPluginProviderFactory(
// IAclModule aclModule
// )
//{
// if (aclModule == null)
// throw new ArgumentNullException("aclModule");
//
// this.aclModule = aclModule;
//}
public ISomeObject Create(IState state)
{
return new SomeObject(state);
// return new SomeObject(state, this.aclModule);
}
pubic void Release(ISomeObject someObject)
{
var disposable = someObject as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
然后使用:
public class Consumer : IConsumer
{
private readonly ISomeObjectFactory someObjectFactory;
public Consumer(ISomeObjectFactory someObjectFactory)
{
if (someObjectFactory == null)
throw new ArgumentNullException("someObjectFactory");
this.someObjectFactory = someObjectFactory;
}
public void DoSomething(IState state)
{
var instance = this.someObjectFactory.Create(state);
try
{
// Use the instance here.
}
finally
{
this.someObjectFactory.Release(instance);
}
}
}
虽然这里没有显示,但工厂可以根据需要在不同的类之间切换,或者在创建时可以将不同的依赖项(在本例中为IState)传递给相同类型的类。
Service Locator is Anti-Pattern除了最罕见的情况外,应该避免这种情况。