开发者

Resolving injected instances when using Activator.CreateInstance

I'm trying to figure out how to have Castle Winds开发者_JAVA百科or resolve dependancies for objects created using Activator.CreateInstance.

Currently when I create objects this way, the dependancies inside the created object do not get resolved. I've had a search around to see if there's a Windsor method that does the same thing whilst also resolving the dependancies but I haven't found anything thus far.

As for why I'm creating instances this way, I'm playing about with a basic text game for a bit of fun and the instances are being created based on user input commands and so I need to create the instance based on a string (currently the command is mapped in a Dictionary to a type which is then created using the above method).

Thanks for any and all help.


AFAIK you can register in castle windsor you can register the so called "named instances" so you can create the object you need by resolving them througth the container without dealing with Activator.CreateInstance that for sure can't perform IoC. Basically you have to register your component with a key:

AddComponent(String key, Type classType) 

and then call

Resolve(string Key)

to have back your component properly created with all dependencies resoved.


To expand on the answer given by Felice I thought it'd be useful to post the solution I came to based on the accepted answer.

Currently my commands are mapped via an IDictionary<TKey,TValue> but will be moved to another medium soon (XML, JSON, etc).

Here's how I'm registering the compnents for user input commands:

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));

  }
}

and to resolve the instance:

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
                };
}


A better implementation, Windsor-wise, would be to utilize a typed factory. With a typed factory, your code would not have to reference the container, because a factory implementation would be automatically created for you.

With a typed factory, your factory could look like this:

public interface IUserInputCommandFactory
{
    IUserInputCommand GetMove();
    IUserInputCommand GetLocate();
    IUserInputCommand GetLookAround();
    IUserInputCommand GetBag();
}

and Windsor would forward each factory method to a corresponding resolve - e.g. GetMove would become container.Resolve<IUserInputCommand>("Move").

See typed factory docs ("'get' methods lookup by name) for more information.

I think this is one of the places where Windsor really shines :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜