gpt4 book ai didi

c# - 使用 windsor 访问在安装时解析的类型

转载 作者:行者123 更新时间:2023-11-30 20:53:37 25 4
gpt4 key购买 nike

我有大量依赖看门狗组件的类。我将对依赖类的引用添加到看门狗实例。

目前我使用下面的代码来完成这个。

   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>() .

显然,如果我能以某种方式访问​​正在解析的类型的实例,就像在 OnCreate() 中那样那也行。

最佳答案

使用自定义工具,您可以将组件的默认激活器更改为执行您想要的操作的激活器。这是一个可行的解决方案:

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

这使用相同的策略,但使用属性注入(inject)。我已经创建了一个组件模型构造贡献者来强制要求注入(inject) IWatchDogServcie 城堡,就像您在构造函数注入(inject)时需要做的那样。这是相关代码:

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

关于c# - 使用 windsor 访问在安装时解析的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19838838/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com