2.2 更新内容 Windsor 3.1

优质
小牛编辑
133浏览
2023-12-01

Windsor 3.1 is a minor update over version 3.0. It does contain a set of new features and fixes that make it a worthwhile update. Below is a (non-comprehensive) list of highlights of the release.

:information_source: For more details see changes.txt and breakingchanges.txt files distributed as part of the package)

Selective open generic components

In version 3.1 a new extension point has been added which allows open generic components to be selective about which closed versions they want to support. Windsor uses this now internally for Lazy<T>; dependencies and for Func<T> dependencies. Windsor will now opt out of satisfying Lazy<int> or Func<string> (since there can never be a string or int component in Windsor.

The new extension point is exposed via IGenericServiceStrategy interface, and can be associated with a component using registration API when registering open generic component.

Container.Register(Component.For(typeof(IMyGenericService<>)).ImplementedBy(typeof(MyImplementation<>), new MyServiceStrategy()));

The interface has very simple contract with a single method:

bool Supports(Type service, ComponentModel component);

The method should return true if the component can and wants to be used to satisfy the service (which is guaranteed to be a closed version of one of open generic services of this component).

Fallback components

The default behavior in Windsor is that whichever components for a given service gets registered first will be the default one. There are cases however, especially in extensibility scenarios where (for example) a facility integrating Windsor with some other tool wants to register some components but allow you to override them so that your implementation is used.

There was no easy way of achieving that in older versions of Windsor (other than making sure you register your implementation before adding the facility, which was... not pretty). In version 3.1 you can now explicitly mark a component as fallback (for all, or selected services it exposes) so that it will be only picked unless other, non-fallback, component for those services is registered and available.

Container.Register(Component.For<IFoo>().ImplementedBy<FallbackFoo>().IsFallback(),
                   Component.For<IFoo>().ImplementedBy<MyBetterFoo>());
// ...
var foo = Container.Resolve<IFoo>(); // will resolve MyBetterFoo

Disabling signed module in proxy generator

IT is now a lot simpler to ensure all proxy types are generated into an unsigned module. If you want to disable signed module replace the default proxy factory with the following.

Container.Kernel.ProxyFactory = new DefaultProxyFactory(disableSignedModule: true);

Changes to InterceptorAttribute

It is now possible to associate multiple interceptors with a type via attributes:

[Interceptor(typeof(InterceptorOne))]
[Interceptor(typeof(InterceptorTwo))]
public class MyClass
{
   // some implementation
}

The attribute is now allowed to be placed on other elements than just classes, like methods or properties. Windsor still only looks for the attribute on classes, but it is possible to extend it.

Enhancements to logging facility

Global logger name

It is now possible to specify a global root log name (works with extended loggers only). All logs coming though Windsor will appear under this root name.

Container.AddFacility<LoggingFacility>(f => f.LogUsing(LoggerImplementation.ExtendedLog4net).ToLog("MyLogName"));

Opting out of logging framework configuration for log4net and NLog

In complex applications using multiple frameworks other than Windsor you may find those other frameworks want to take over configuration of your logging framework (be it log4net or NLog). Since both NLog and log4net store their configuration in a static property this may lead to some issues.

For those cases to avoid frameworks competing for ownership of logging configuration Windsor can now opt out of configuring the logging framework using the following code:

Container.AddFacility<LoggingFacility>(f => f.UseLog4Net().ConfiguredExternally());

Calling ConfiguredExternally() is telling Windsor "Do use log4net (or NLog) but do not attempt to configure it. It will be configured somewhere else".

Specifying custom NLog configuration file

A new overload to UseNLog has been added to allow you to specify custom configuration file (other than the default called nlog.config in a single call.

Container.AddFacility<LoggingFacility>(f => f.UseNLog("someOtherFile.xml"));

Notice that similar overload exists for log4Net since Windsor 3.0.