我正在为服务注册多个组件,并且我想为组件提供额外的元数据,而无需解析服务。
使用Microsoft扩展性框架,您可以为导出提供其他元数据,如下所示 MEF 元数据和元数据视图,温莎是否有类似的东西?
我目前正在尝试将我的组件包装在一个具有 2 个属性的类中,IMetadata 和 Lazy 需要时惰性会解析组件。
public class Program
{
public static void Main(string[] args)
{
var container = new WindsorContainer();
// register the wrapped object that contains the Component metadata and a lazy to resolve the component
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>()
.Configure(config =>
{
// create wrapper
var wrapper = new WrappedComponent();
wrapper.ComponentImpl = new Lazy<IService>(() => container.Resolve<IService>(config.Name));
// add metadata to the wrapper
if (config.Implementation.IsDefined(typeof(ComponentMetadataAttribute), false))
{
var metadata = (IComponentMetadata)config.Implementation.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)[0];
wrapper.Metadata = metadata;
}
// set the component to the wrapper
config.Instance(wrapper);
})
// also set service to wrapper
.WithService.Select((impl, services) => new List<Type>() { typeof(WrappedComponent) }));
// register the components
container.Register(
Classes.FromThisAssembly()
.BasedOn<IService>().Configure(config =>
{
if (config.Implementation.IsDefined(typeof(ComponentMetadataAttribute), false))
{
var metadata = (IComponentMetadata)config.Implementation.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)[0];
config.Named(metadata.Name);
}
}));
}
}
public class WrappedComponent
{
public IComponentMetadata Metadata { get; set; }
public Lazy<IService> ComponentImpl { get; set; }
}
[ComponentMetadata]
public class MyComponent : IService
{
public void Operation()
{
// Do stuff
}
}
public interface IService
{
void Operation();
}
public class ComponentMetadataAttribute : Attribute, IComponentMetadata
{
public string Name { get; set; }
public string Description { get; set; }
public string SomeOtherMetadata { get; set; }
}
public interface IComponentMetadata
{
string Name { get; set; }
string Description { get; set; }
string SomeOtherMetadata { get; set; }
}
您可以通过处理元数据和延迟加载组件对WrappedComponent
类的提取来使WrappedComponent
更加通用并简化注册。
WrappedComponent
获取IKernel
(来自温莎城堡(,并使用它来确定从中检索元数据的TComponent
服务的实现类型。它还使用 IKernel
来初始化 Lazy
对象。请记住处理TComponent
的发布,因为我们正在显式解决它。
public class WrappedComponent<TComponent> : IDisposable
{
private readonly IKernel kernel;
public WrappedComponent(IKernel kernel)
{
this.kernel = kernel;
var componentType = this.kernel.GetHandler(typeof(TComponent)).ComponentModel.Implementation;
this.Metadata = componentType.GetCustomAttributes(typeof(ComponentMetadataAttribute), false)
.Cast<ComponentMetadataAttribute>().FirstOrDefault();
this.ComponentImpl = new Lazy<TComponent>(() => this.kernel.Resolve<TComponent>());
}
public IComponentMetadata Metadata { get; }
public Lazy<TComponent> ComponentImpl { get; }
public void Dispose()
{
if (this.ComponentImpl.IsValueCreated)
{
this.kernel.ReleaseComponent(this.ComponentImpl.Value);
}
}
}
注册变得像...
container.Register(Component.For(typeof(WrappedComponent<>)).LifestyleTransient());
container.Register(Classes.FromThisAssembly().BasedOn<IService>().WithService.FromInterface().LifestyleTransient());
我假设了一种Transient
的生活方式,但无论您使用哪种生活方式,最好在WrappedComponent
和IService
中使用相同的生活方式。
IService
、MyComponent
、ComponentMetadataAttribute
和IComponentMetadata
保持不变。