我正在试图弄清楚如何让Castle Windsor解决使用Activator.CreateInstance
创建的对象的依赖关系。
目前,当我以这种方式创建对象时,创建对象内的依赖关系无法解析。我有一个搜索周围,看看是否有一个Windsor方法做同样的事情,同时也解决了依赖性,但到目前为止我还没有找到任何东西。
至于为什么我以这种方式创建实例,我正在玩一个基本的文本游戏,有点乐趣,实例是基于用户输入命令创建的,所以我需要创建基于的实例一个字符串(当前命令在Dictionary中映射到一个类型,然后使用上面的方法创建)。
感谢您的帮助。
答案 0 :(得分:2)
AFAIK你可以在城堡windsor注册你可以注册所谓的“命名实例”,这样你就可以通过容器解析它们来创建你需要的对象,而无需处理Activator.CreateInstance,肯定无法执行IoC。 基本上,您必须使用密钥注册组件:
AddComponent(String key, Type classType)
然后致电
Resolve(string Key)
让所有依赖项恢复正确创建组件。
答案 1 :(得分:2)
为了扩展Felice给出的答案,我认为根据接受的答案发布解决方案是有用的。
目前我的命令是通过IDictionary<TKey,TValue>
映射的,但很快就会被移到另一个媒体上(XML,JSON等)。
以下是我如何注册用户输入命令的组件:
public void InstallUserCommands(IWindsorContainer container)
{
var commandToClassMappings = new Dictionary<string, string>
{
{"move", "MoveCommand"},
{"locate","LocateSelfCommand"},
{"lookaround","LookAroundCommand"},
{"bag","LookInBagCommand"}
};
foreach (var command in commandToClassMappings)
{
var commandType = Type.GetType("TheGrid.Commands.UserInputCommands." + command.Value);
container.Register(Component.For(commandType).Named(command.Key));
}
}
并解决实例:
public UserCommandInputMapperResponse Invoke(UserCommandInputMapperRequest request)
{
var container = new WindsorContainer();
container.Install(FromAssembly.This());
IUserInputCommand instance;
try
{
instance = container.Resolve<IUserInputCommand>(request.CommandName.ToLower().Trim());
}
catch (Exception)
{
instance = null;
}
return new UserCommandInputMapperResponse
{
CommandInstance = instance
};
}
答案 2 :(得分:1)
更好的实施方式,温莎方面,将是利用一个打字的工厂。使用类型化工厂,您的代码不必引用容器,因为将自动为您创建工厂实现。
使用打字工厂,您的工厂可能如下所示:
public interface IUserInputCommandFactory
{
IUserInputCommand GetMove();
IUserInputCommand GetLocate();
IUserInputCommand GetLookAround();
IUserInputCommand GetBag();
}
并且Windsor会将每个工厂方法转发给相应的解决方案 - 例如GetMove
将成为container.Resolve<IUserInputCommand>("Move")
。
有关详细信息,请参阅typed factory docs ("'get' methods lookup by name)。
我认为这是温莎真正发光的地方之一:)