我想使用Castle Windsor在WebApi应用程序中实现依赖注入。我有以下示例代码:
接口-
public interface IWatch
{
{
DateTime GetTime();
}
}
遵循观察类实现了IWatch接口-
public class Watch:IWatch
{
public DateTime GetTime()
{
return DateTime.Now;
}
}
WatchController控制器- WebApi,如下所示-
public class WatchController : ApiController
{
private readonly IWatch _watch;
public WatchController()
{
_watch = new Watch();
}
//http://localhost:48036/api/Watch
public string Get()
{
var message = string.Format("The current time on the server is: {0}", _watch.GetTime());
return message;
}
}
目前,我正在使用WatchController构造函数中的Watch初始化IWatch对象。我想使用Windsor Castle依赖注入原理来消除在构造函数中初始化IWatch的依赖。
有没有人能告诉我在这种WebApi情况下实现依赖注入的步骤?提前感谢!
发布于 2013-11-19 20:38:39
CodeCaster,Noctis和Cristiano感谢你们的帮助和指导。我刚刚得到了上面问题的解决方案-
第一步是使用nuget在WebApi解决方案中安装Windsor.Castle包。
考虑下面的代码片段-
Interface IWatch.cs接口
public interface IWatch
{
DateTime GetTime();
}
Class Watch.cs
public class Watch:IWatch
{
public DateTime GetTime()
{
return DateTime.Now;
}
}
ApiController WatchController.cs的定义如下:-
public class WatchController : ApiController
{
private readonly IWatch _watch;
public WatchController(IWatch watch)
{
_watch = watch;
}
public string Get()
{
var message = string.Format("The current time on the server is: {0}", _watch.GetTime());
return message;
}
}
在控制器中,我们通过WatchController构造函数中的IWatch对象注入了依赖项。我已经使用IDependencyResolver和IDependencyScope在web中实现了依赖注入。IDependencyResolver接口用于解析请求作用域之外的所有内容。
WindsorDependencyResolver.cs
internal sealed class WindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
public void Dispose()
{
}
}
WindsorDependencyScope.cs
internal sealed class WindsorDependencyScope : IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public WindsorDependencyScope(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
_scope = container.BeginScope();
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public void Dispose()
{
_scope.Dispose();
}
}
WatchInstaller.cs
安装程序是实现IWindsorInstaller接口的简单类型。该接口只有一个名为Install的方法。该方法获取容器的一个实例,然后它可以使用fluent注册API来注册组件:
public class WatchInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
//Need to Register controllers explicitly in your container
//Failing to do so Will receive Exception:
//> An error occurred when trying to create //a controller of type
//> 'xxxxController'. Make sure that the controller has a parameterless
//> public constructor.
//Reason::Basically, what happened is that you didn't register your controllers explicitly in your container.
//Windsor tries to resolve unregistered concrete types for you, but because it can't resolve it (caused by an error in your configuration), it return null.
//It is forced to return null, because Web API forces it to do so due to the IDependencyResolver contract.
//Since Windsor returns null, Web API will try to create the controller itself, but since it doesn't have a default constructor it will throw the "Make sure that the controller has a parameterless public constructor" exception.
//This exception message is misleading and doesn't explain the real cause.
container.Register(Classes.FromThisAssembly()
.BasedOn<IHttpController>()
.LifestylePerWebRequest());***
container.Register(
Component.For<IWatch>().ImplementedBy<Watch>()
);
}
}
最后,我们需要用Global.asax.cs (Application_Start方法)中的Windsor实现替换默认的依赖解析器,并安装依赖项:
private static IWindsorContainer _container;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureWindsor(GlobalConfiguration.Configuration);
}
public static void ConfigureWindsor(HttpConfiguration configuration)
{
_container = new WindsorContainer();
_container.Install(FromAssembly.This());
_container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true));
var dependencyResolver = new WindsorDependencyResolver(_container);
configuration.DependencyResolver = dependencyResolver;
}
发布于 2013-11-12 16:39:05
阅读Mark Seemann关于windsor plumbing for webapi的帖子。
发布于 2013-11-11 19:40:28
我没有直接与Castle Windsor合作,但我相信逻辑应该是类似的:
您的WatchController
ctor应该如下所示:
public WatchController(IWatch watch)
{
_watch = watch;
}
这就是你inject
依赖的地方。
你应该有一个等同于定位器的东西,你可以在其中注册你的WatchController
类,并告诉它应该接收哪个手表,这取决于你想要什么……设计/运行时间、星期几、随机数...不管你需要的是什么.
以下代码来自MVVM-Light,但应澄清上面的段落:
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
// This will run in design mode, so all your VS design data will come from here
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
// This will run REAL stuff, in runtime
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
// You register your classes, so the framework can do the injection for you
SimpleIoc.Default.Register<MainViewModel>();
...
}
https://stackoverflow.com/questions/19905186
复制相似问题