我有很多类,具体取决于看门狗组件。我将对依赖类的引用添加到监视程序实例。
目前我使用以下代码来完成此任务。
class MyClass {
public MyClass(IWatchDog watchDog) {
watchDog.WatchingType = typeof(MyClass);
}
}
我的安装程序:
class IoC: IWindsorInstaller {
public void Install(IWindsorContainer container, IConfigurationStore store) {
container.Register(Component.For<MyClass>());
container.Register(Component.For<IWatchDog>().ImplementedBy<WatchDogService>());
}
}
是否可以让安装程序为我执行此任务?这是我在伪代码中的想法,OnResolving是我想象的方法:
class IoC : IWindsorInstaller {
public void Install(IWindsorContainer container, IConfigurationStore store) {
container.Register(Component.For<MyClass>());
container.Register(
Component.For<IWatchDog>()
.ImplementedBy<WatchDogService>()
.OnResolving<IWatchDog>(
new Action((Type typeBeingResolved, IWatchDog instance) =>
instance.WatchingType = typeBeingResolved));
}
}
因此,在这种情况下,如果调用typeBeingResolved
,我认为typeof(MyClass)
等于container.Resolve<MyClass>()
,如果有人调用null
,则container.Resolve<IWatchDog>()
。{/ p>
显然,如果我可以以某种方式访问正在解析的类型的实例,就像在OnCreate()
中那样可以正常工作。
答案 0 :(得分:4)
使用自定义工具,您可以将组件的默认激活器更改为可以执行所需操作的激活器。这是一个有效的解决方案:
using Castle.Core;
using Castle.MicroKernel;
using Castle.MicroKernel.ComponentActivator;
using Castle.MicroKernel.Context;
using Castle.MicroKernel.Facilities;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComponentCreater
{
public interface IWatchDogService
{
Type WatchingType { get; set; }
}
public class WatchDogService : IWatchDogService
{
public Type WatchingType { get; set; }
}
public class WatchedClassViaConstructor
{
private readonly IWatchDogService watchDogService;
public WatchedClassViaConstructor(IWatchDogService watchDogService)
{
this.watchDogService = watchDogService;
}
public void Print()
{
Console.WriteLine(this.watchDogService.WatchingType.Name);
}
}
public class WatchDogFacility : AbstractFacility
{
protected override void Init()
{
this.Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;
}
private void Kernel_ComponentModelCreated(ComponentModel model)
{
model.CustomComponentActivator = typeof(WatchedComponentActivator);
}
}
public class WatchedComponentActivator : DefaultComponentActivator
{
public WatchedComponentActivator(ComponentModel model, IKernel kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)
: base(model, kernel, onCreation, onDestruction)
{
}
protected override object CreateInstance(CreationContext context, ConstructorCandidate constructor, object[] arguments)
{
object component = base.CreateInstance(context, constructor, arguments);
if (arguments != null)
{
IWatchDogService watchDogService = arguments.FirstOrDefault(arg => arg is IWatchDogService) as IWatchDogService;
if (watchDogService != null)
{
watchDogService.WatchingType = component.GetType();
}
}
return component;
}
}
class Program
{
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
container.AddFacility<WatchDogFacility>();
container.Register(
Component.For<IWatchDogService>()
.ImplementedBy<WatchDogService>()
.LifestyleTransient(),
Component.For<WatchedClassViaConstructor>()
);
WatchedClassViaConstructor obj = container.Resolve<WatchedClassViaConstructor>();
obj.Print();
Console.ReadLine();
}
}
}
如果您正在使用AOP并希望让您的课程保持整洁,您可以使用上面稍微修改过的版本,让您观看的课程如下所示:
public class WatchedClassViaInheritance : WatchedClass
{
public void Print()
{
Console.WriteLine(this.WatchDogService.WatchingType.Name);
}
}
这使用相同的策略,但使用属性注入。我已经创建了一个组件模型构造贡献者来强制执行castle以要求注入IWatchDogServcie,就像它是构造函数注入时需要做的那样。这是代码:
namespace ComponentCreater2
{
using Castle.Core;
using Castle.MicroKernel;
using Castle.MicroKernel.ComponentActivator;
using Castle.MicroKernel.Context;
using Castle.MicroKernel.Facilities;
using Castle.MicroKernel.ModelBuilder;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public interface IWatchDogService
{
Type WatchingType { get; set; }
}
public class WatchDogService : IWatchDogService
{
public Type WatchingType { get; set; }
}
public interface IIsWatched
{
IWatchDogService WatchDogService { get; set; }
}
public abstract class WatchedClass : IIsWatched
{
public IWatchDogService WatchDogService { get; set; }
}
public class WatchedClassViaInheritance : WatchedClass
{
public void Print()
{
Console.WriteLine(this.WatchDogService.WatchingType.Name);
}
}
public class WatchDogFacility : AbstractFacility
{
protected override void Init()
{
this.Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;
this.Kernel.ComponentModelBuilder.AddContributor(new RequireWatchDogService());
}
private void Kernel_ComponentModelCreated(ComponentModel model)
{
if (typeof(IIsWatched).IsAssignableFrom(model.Implementation))
{
model.CustomComponentActivator = typeof(WatchedComponentActivator);
}
}
}
public class WatchedComponentActivator : DefaultComponentActivator
{
public WatchedComponentActivator(ComponentModel model, IKernel kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)
: base(model, kernel, onCreation, onDestruction)
{
}
protected override void SetUpProperties(object instance, CreationContext context)
{
base.SetUpProperties(instance, context);
IIsWatched watched = instance as IIsWatched;
if (watched != null)
{
watched.WatchDogService.WatchingType = instance.GetType();
}
}
}
public class RequireWatchDogService : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
model.Properties.Where(prop => prop.Dependency.TargetType == typeof(IWatchDogService))
.All(prop => prop.Dependency.IsOptional = false);
}
}
class Program2
{
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
container.AddFacility<WatchDogFacility>();
container.Register(
Component.For<IWatchDogService>()
.ImplementedBy<WatchDogService>()
.LifestyleTransient(),
Component.For<WatchedClassViaInheritance>()
);
WatchedClassViaInheritance obj = container.Resolve<WatchedClassViaInheritance>();
obj.Print();
Console.ReadLine();
}
}
}