How to add facility configuration in Castle Windsor v3+ using code? - inversion-of-control

In Castle Windsor v3+ the IWindsorContainer.AddFacility<T>(string idlnConfiguration) method has been deprecated. In the old version you could use this method to add dynamic configuration by calling IConfigurationStore.AddFacilityConfiguration(string key, IConfiguration config) where "idlnConfiguration" and "key" were the same in the calls.
For example:
store.AddFacilityConfiguration("quartzNet", facilityConfig);
container.AddFacility<QuartzFacility>("quartzNet");
What is the recommended way of doing this in Windsor 3? The message on the ObsoleteAttribute points at using container.AddFacility<T>() instead, but I can't see how.

the recommended way is to use
container.AddFacility<SomeFacility>(f => f.Configure("me").Here());
obviously the facility has to support this.

Related

Map fields with the same name using Lombok

I'm using Lombok in a Spring Boot application, The MongoDB object are the same as my domain model so when I do the mapping I have to specify all the field names even they are the same
public static Receipt toModel(MGReceipt mgReceipt) {
return Receipt.builder()
.id(mgReceipt.getId())
.date(mgReceipt.getDate())
.dueDate(mgReceipt.getDueDate())
...
.build();
}
Is there a way to simplfy this , and avoid to specify all the properties names from MGReceipt that match Receipt ones, with Lombok ? or maybe I should use another solution for the mapping like mapstruct
That's exactly what MapStruct was created for. MapStruct also plays quite nicely with lombok, as described here. Also lombok's #Builder is supported, if you want that.
Make sure you use recent versions of both lombok and MapStruct, and don't forget to add the lombok-mapstruct-binding as a third annotation processor to make sure MapStruct can see everything that lombok generates.
I'm not aware of any easier/nicer framework to do such a mapping. There's also no nice way of doing it manually, as that would require some nasty reflection stuff to identify similarly named fields/getters/setters.

Autofac Interface Ambiguity

"The ambiguity, is in the box" - Monty Python.
Autofac is having a problem resolving an interface. See attached solution.
The Interface, IAmbiguous, is defined in project ACommon. It is implemented in project AInjectable. The AInjectable project does not / cannot reference ACommon. The AInjectable project defines IAmbiguous as an existing item brought in with a file link.
The UI project calls ACommon Inject and attempts to register the AInjectable assembly. IAmbiguous is not ambiguous initially but after a builder.RegisterAssemblyTypes command it becomes "ambiguous in the namespace." There is no error thrown when the container is built but the registration is not there.
Registration can be done "AsImplementedInterfaces" if Named and Keyed is not used. But then there is no way to Resolve the registration because the service IAmbiguous is "ambiguous in the namespace."
This question was double-posted as an issue on Autofac. It is not an Autofac problem. I will copy/paste the answer from the issue in here; for future readers, if you want to see the repro solution, go check out the full issue
What you're doing by including the same interface in two different assemblies isn't something you should be doing. Note that by doing that, your AInjectable class is not implementing the interface from the ACommon project. It's implementing a different but identically named interface.
This sort of thing is a problem - having the same type (interface, class, whatever) name in two different assemblies. We even had a problem (#782) where we had a System.SerializableAttribute in Autofac as a shim for .NET Core. You really just can't do that.
You'll also see the same thing if you try to make a static extension method class that has the same namespace and name as some other static extension method class. Ambiguous references.
Without doing Reflection.Emit style code generation, you won't be able to declare an interface in one assembly ("Assembly A") and implement that interface in a different assembly ("Assembly B") without having Assembly B reference Assembly A. That's just how .NET works. What you're seeing is a manifestation of that when you use Autofac, but it's not caused by Autofac. It's caused by you doing something you shouldn't be doing in .NET.
The fix is to define your interfaces in a separate assembly that everyone implementing the interfaces can reference. (Or you can try to dynamically generate code using Reflection.Emit or Roslyn or something, but that's waaaay harder.)

Utilizing RijndaelManaged, Enterprise Library and Autofac together

I'm newly experimenting with the cryptography application block while using Autofac as the container.
As a result, I'm using the nuget package EntLibContrib 5.0 - Autofac Configurator.
With the DPAPI Symmetric Crypto Provider, I was able to encrypt/decrypt data just fine.
However, with RijndaelManaged, I receive an ActivationException:
Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type ISymmetricCryptoProvider, key "RijndaelManaged" ---> Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'RijndaelManaged (Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.ISymmetricCryptoProvider)' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
Per instructions here: http://msdn.microsoft.com/en-us/library/ff664686(v=pandp.50).aspx
I am trying to inject CryptographyManager into MyService.
My bootstrapping code looks like this:
var builder = new ContainerBuilder();
builder.RegisterEnterpriseLibrary();
builder.RegisterType<MyService>().As<IMyService>();
_container = builder.Build();
var autofacLocator = new AutofacServiceLocator(_container);
EnterpriseLibraryContainer.Current = autofacLocator;
App.config has this info defined for symmetricCryptoProviders:
name: RijndaelManaged
type: Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
algorithmType:System.Security.Cryptography.RijndaelManaged
protectedKeyFilename:[path_to_my_key]
protectedKeyProtectionScope: LocalMachine
Anyone have experience in this combination of technologies?
After some testing, I believe I may go with a Unity container instead, since I have no preference in IOC containers other than whatever I use should integrate nicely with ASP.NET MVC3 and http-hosted WCF services.
My bootstrapping code then becomes more simple:
var container = new UnityContainer()
.AddNewExtension<EnterpriseLibraryCoreExtension>();
container.RegisterType<IMyService, MyService>();
I actually wrote the Autofac EntLib configurator (with some help from some of the P&P folks). It's been tested with the exception handling block and logging block, but I haven't tried it with the cryptography stuff.
EntLib has an interesting thing where it sometimes requires registered services to be named, and I'm guessing from the exception where it says...
type ISymmetricCryptoProvider, key "RijndaelManaged"
...I'm thinking EntLib wants you to register a named service, like:
builder.Register(c =>
{
// create the HashAlgorithmProvider using
// RijndaelManaged algorithm
})
.Named<ISymmetricCryptoProvider>("RijndaelManaged");
I'm sort of guessing at the exact registration since, again, I've not got experience with it or tested it, but the idea is that EntLib is trying to register a named service whereas the actual service isn't getting registered with the name.
The RegisterEnterpriseLibrary extension basically goes through and tries to use the same algorithm that Unity uses to do the named/unnamed registrations. I'm guessing you've encountered an edge case where something's not getting handled right. EntLib is pretty well tied to Unity, even if they did try to abstract it away.
If you're not tied to Autofac, Unity is going to be your lowest-friction path forward. I like the ease of use and more lightweight nature of Autofac, and my apps are tied to it, so I needed everything to work that way; if you don't have such an affinity, might be easier to just use Unity.
Sorry that's not a super answer. EntLib wire-up in IoC is a really complex beast.

Autofac aop wildcard: is it possible?

The canonical way of using AOP in Autofac is to declare interceptor on each component:
builder.RegisterType<Filter1>().As<IFilter>()
.EnableInterfaceInterceptors();
In my project I have a lot (tens of) IFilter implementations, so adding and maintaining them is inconvenient. I would prefer an ability to intercept all instances of service. Something like:
builder.EnableInterfaceInterceptors<IFilter>();
Is it possible?
I am not sure if EnableInterfaceInterceptors can handle multiple registrations, but if it can this should work:
builder.RegisterAssemblyTypes(assemblies).Where(t => t.IsAssignableTo<IFilter>())
.EnableInterfaceInterceptors();
If you need, this can be wrapped into an extension method (like almost all the ContainerBuilder registration methods) to give you the exact syntax you requested above.

How can I find out which bundle or plugin invoked (shared) code?

I want to create something like 'BundleLocal' variables, just like ThreadLocal variables, but instead of looking them up by Thread.currentThread() I need to look them up by bundle context.
The point is that I have a framework plugin 'F', and other plugins 'A', 'B', etc. using that framework. The framework contains a singleton which I want to refactor such that I have a singleton instance per bundle. MySingleton.getInstance() would then create/return a dedicated instance for each plugin. The problem is that within MySingleton.getInstance() I'd need to find out which of the plugins ('A', 'B', ..) called that method.
I could do it with a hack, obtaining the call stack with
StackTraceElement[] ste=new Throwable().getStackTrace();
and then querying the bundle context by class for each element:
org.osgi.framework.FrameworkUtil.getBundle(Class c).getBundleContext()
but sincerely hope that there exists a better way to obtain the bundle context or bundle id from within framework 'F'.
Any advice on how to do this more elegantly?
I would recommend to inject the information from where the call comes instead of trying to determine where it comes from. Something like this:
MyMultiton.getInstance(bundleContext)
Because of the modular nature of OSGi (and its isolated class loaders) singletons don't work (as you found out).
If you're refactoring, one option would be to simply add indirection. In ActivatorA:
public static Singleton getSingleton() {
Framework.getSingleton(BUNDLE_ID);
}
Then plugin A uses ActivatorA.getSingleton() and plugin B uses ActivatorB.getSingleton().
The other potential way is to provide a ComponentFactory and use Declarative Service to inject the appropriate Component (OSGi service) into plugin A and plugin B (everybody gets their own instance of the Component). But this is a more dynamic, more decoupled implementation of my first example.