Caslte Windsor Proxy Generation Options - c#

I've been struggling to find anything online, so I thought I'd see if anyone else knows how to sort this little issue I'm having.
I've got a scenario where I want to create a proxy object so that various other interfaces can be added to the same object. So far, I've not had any issues with this. One of my other requirements is to be able to set an attribute on the proxy-generated class.
I've been able to do this successfully using Castle DynmaicProxy manually, using something along the lines of:
var serviceOptions = new ProxyGenerationOptions();
// Create MyAttribute
var args = new object[] { "SomeName" };
var constructorTypes = new[] { typeof(String) };
var constructorInfo = typeof(MyAttribute).GetConstructor(constructorTypes);
var attributeBuilder = new CustomAttributeBuilder(constructorInfo, args);
serviceOptions.AdditionalAttributes.Add(attributeBuilder);
However, I'm using windsor to resolve my dependencies through injection. Windsor does provide some proxy options, such as:
configurer.Proxy.AdditionalInterfaces(interfaces);
configurer.Proxy.MixIns(r => r.Component(type));
But it does not seem to offer options for custom attributes. Does anyone know how this can be achieved? Many thanks.

In the end, I found an alternative solution from taking Phil's idea and from scanning the Castle source.
I created a custom ProxyFactory class that extends the DefaultProxyFactory from the Castle.Windsor assembly. The only method I implemented was the CustomizeOptions method, which by default, is empty.
From here, I hook into the ExtendedProperties of ComponentModel to get a collection of CustomAttributeBuilder instances I add when registering my components.
Full code below:
internal const string PROXY_ATTRIBUTES_PROPERTY_KEY = "custom.proxy.attributes";
protected override void CustomizeOptions(ProxyGenerationOptions options, IKernel kernel, ComponentModel model, object[] arguments)
{
if (model.ExtendedProperties.Contains(PROXY_ATTRIBUTES_PROPERTY_KEY))
{
var proxyAttributes = (IEnumerable<CustomAttributeBuilder>)model.ExtendedProperties[PROXY_ATTRIBUTES_PROPERTY_KEY];
foreach (var attribute in proxyAttributes)
{
options.AdditionalAttributes.Add(attribute);
}
}
base.CustomizeOptions(options, kernel, model, arguments);
}
configurer.ExtendedProperties(new Property(CustomProxyFactory.PROXY_ATTRIBUTES_PROPERTY_KEY, configurator.ProxySettings.CustomAttributes));

The standard ProxyGroup provides access to a subset of the proxy generation options. However, it is relatively straight forward to create your own descriptor to modify other options and add it to the component registration. The trick is to use an extension method to retrieve the proxy options used by the built-in ProxyGroup registration helper.
public class ProxyCustomAttributeBuilderDescriptor : IComponentModelDescriptor
{
public void BuildComponentModel(IKernel kernel, ComponentModel model)
{
var options = model.ObtainProxyOptions();
// ... do whatever you need to customise the proxy generation options
}
public void ConfigureComponentModel(IKernel kernel, ComponentModel model)
{
}
}
Then when you register your component simply add this descriptor:
configurer.AddDescriptor(new ProxyCustomAttributeBuilderDescriptor());

Related

Masstransit configuring a generic consumer

I'm in the process of integrating a messaging broker within our existing application using MassTransit.
We had already implemented a kind of command handler that had generic implementations, like this:
public class MyCommandHandler: CommandHandlerBase<MyCommand>
Now it was relatively easy to make a generic Consumer that would do some boiler plating and would hand off the work to the ready command handler, requested from the DI container.
public class CommandConsumer<TCommand> : IConsumer<TCommand>
Which I could then easily register through the Microsoft DI thusly:
cfg.AddConsumer<CommandConsumer<MyCommand>>(x => some configuration...);
This all worked great, so I moved on to the next step, namely to extract the consumer registration(s) to a common helper method and this is where I'm a bit stumped. The method (currently) looks a bit like this
public static IServiceCollection ConfigureMassTransit(this IServiceCollection services, params Type[] consumerTypes)
{
return
services.AddMassTransit(cfg =>
{
foreach (var consumerType in consumerTypes)
{
cfg.AddConsumer(consumerType);
}
// or cfg.AddConsumers(consumerTypes);
cfg.AddBus(context => Bus.Factory.CreateUsingRabbitMq(config =>
{
var host = config.Host("localhost", "/",
h =>
{
h.Username("guest");
h.Password("guest");
});
config.ConfigureEndpoints(context);
}));
});
}
which would be called as services.ConfigureMassTransit(typeof(CommandConsumer<MyCommand>));
This again works, but what I can't figure out is how to add the additional configuration to the registration; the overload that takes an Action is only available when using the generic signature, which you can't use directly when you only have the Type available. I tried adding a marker class CommandConsumer: IConsumer to the CommandConsumer<TCommand> and making CommandConsumerDefinition : ConsumerDefinition<CommandConsumer>, and changing the above to cfg.AddConsumer(consumerType, typeof(CommandConsumerDefinition));, but that doesn't work as the ConfigureConsumer override is never hit.
How am I supposed to add additional configuration to a Consumer for which I don't know the type at compile time?
Chris' answer put me on the path to a working solution. Making the CommandConsumerDefinition generic allowed me to use reflection to construct both types in the same way at runtime. This allowed MassTransit to wire up the configuration in the expected manner.
In the end, I also used a "marker" attribute that would hold the type of the command contract, so they could be discovered rather than having to be entered as a parameter at startup.
public static IServiceCollectionConfigurator ConfigureMassTransitConsumers(this IServiceCollectionConfigurator serviceConfigurator, Assembly assembly)
{
foreach (var type in assembly.GetTypes())
{
var attributes = type.GetCustomAttributes(typeof(RegisterCommandConsumerAttribute), false);
if (attributes.Length <= 0) continue;
foreach (var attribute in attributes)
{
if (attribute is RegisterCommandConsumerAttribute registerCommandConsumerAttribute)
{
Type consumerType = typeof(CommandConsumer<>).MakeGenericType(registerCommandConsumerAttribute.CommandType);
Type consumerDefinitionType = typeof(CommandConsumerDefinition<>).MakeGenericType(registerCommandConsumerAttribute.CommandType);
serviceConfigurator.AddConsumer(consumerType, consumerDefinitionType);
}
}
}
return serviceConfigurator;
}
Because of the automatic discovery, we were already in the realm of reflection, so this seemed like an acceptable solution. This way we can have generic consumers and definitions without having to add a new class for every command contract we have.

Autofac optional/lazy dependencies

If I put Lazy in constructor of my object, and X is not registered in container I got dependency resolution exception.
Why am I getting this exception? I dislike it, because I cannot choose component at runtime. Example usecase:
class Controller
{
public Controller(Lazy<A> a, Lazy<B> b) { /* (...) */ }
Lazy<A> a;
Lazy<B> b;
public IActionResult Get(){
if(someConfig)
return Json(a.Value.Execute());
else
return Json(b.Value.Execute());
}
}
To do so I need to register both components A an B. My program fails even if B is never used. I would like to have B be optional, and still managed by autofac.
This is even bigger issue if I have list of components, and want only one to be used. For example:
class Controller
{
Controller(IEnumerable<Component> components) { /* (...) */ }
IActionResult Get()
{
return components.First(n => n.Name == configuredComponent).Execute();
}
}
I am no longer getting exception is something is not registered, however still everything is constructed. Also it would be awkward to use.
If you add a reference to a Lazy<T> component, Autofac has to know (basically) how to create the internal function that will run should you want to resolve it, even if you don't resolve it.
Basically, it needs to be able to create this in memory:
var lazy = new Lazy<T>(() => scope.Resolve<T>());
Autofac requires all of the things you want to resolve to be registered. It doesn't let you register things on the fly - it must be explicit. So the thing you're trying to do won't work (as you saw).
Instead, use a single interface and two different implementations of that interface. Change the registration based on your configuration value.
var builder = new ContainerBuilder();
if(someConfig)
{
builder.RegisterType<A>().As<IService>();
}
else
{
builder.RegisterType<B>().As<IService>();
}
Then in your controller, inject the interface rather than the concrete class.
public MyController(Lazy<IService> service)
There are also other options you could do, like use metadata for components or keyed services. For example, you could add some metadata based on your configuration and resolve using that.
builder.RegisterType<A>()
.As<IService>()
.WithMetadata("Name", "a");
builder.RegisterType<B>()
.As<IService>()
.WithMetadata("Name", "b");
In the controller, you'd get a dictionary of them:
public MyController(IEnumerable<Meta<IService>> services)
{
var service = services.First(s => s.Metadata["Name"].Equals(someConfig);
}
That's a very short example, but the docs show a lot more.
In any case, the interface is really going to be your key to success. If you're just using concrete classes, they'll have to be registered whether you use them or not.

Configuring MassTransit's Ninject bindings after initialisation

I want to configure MassTransit at one point in my code (using WebActivator) and configure the message handlers in another (a Ninject module). Is there a way I can achieve this? The documentation here shows how to perform what I need in one step, but to do anyhting else, it looks like I need to get an instance of a ServiceBusConfigurator, which doesn't seem to be available from the preexisting IServiceBus
Configuration and Creation of the IServiceBus cannot be separated.
That means, the only option you have is to gather the configuration information some more time before creating the bus.
As the doc you linked states, the meta data information made available by ninject is not sufficient to create the subscriptions. This basically means that you've got to create your own metadata model. Let's make an example, which can be used with single registrations but also with convention based registrations:
Hint: You should treat the following code snippets as psuedo code as i've written them from memory. It's highly likely that it won't compile.
Metadata Model
public class SubscriptionMetadata
{
public SubscriptionMetadata(Type consumer)
{
if(!typeof(IConsumer).IsAssignableFrom(consumer))
{
string message = string.Format(
"{0} does not implement {1}",
typeof(IConsumer).Name,
consumer.Name);
throw new ArgumentOutOfRangeException("consumer", message);
}
this.ConsumerType = consumer;
}
public Type ConsumerType { get; private set; }
}
Registration of Metadata
Now this can be used like this in a Ninject module:
Bind<SubscriptionMetadata>()
.ToConstant(new SubscriptionMetadata(typeof(FooConsumer));
If you're going to use it a lot i'd recommend writing an extension method:
public static class SubscriptionBindingExtensions
{
public static void BindConsumer<T>(this IBindingRoot bindingRoot)
where T : IConsumer
{
Bind<SubscriptionMetadata>()
.ToConstant(new SubscriptionMetadata(typeof(T));
}
}
and usage (#Module):
BindConsumer<FooConsumer>();
IServiceBus creation
Now you would adapt the IServiceBus creation as follows:
var kernel = new StandardKernel();
// 2nd Step left out: load all IModule`s ..
var bus = ServiceBusFactory.New(sbc =>
{
//other configuration options
foreach(var metadata in kernel.GetAll<SubscriptionMetadata>())
{
sbc.Subscribe(subs =>
{
subs.Consumer(metadata.ConsumerType, kernel)
});
}
});
Convention based binding of Consumers
It can also be used in conjunction with conventions by leveraging the IBindingCreator interface. If you wish, i can post an example.

How to inject dependencies via a construction delegate

I'm using a third-party library that has a setup structure like this:
IEngine engine = /* singleton provided elsewhere */
var server = new FooServer();
server.AddService("Data1", () => new Data1(engine));
server.AddService("Data2", () => new Data2(engine));
server.Start();
...
server.Dispose();
(The lambda is essentially a factory method; it will internally invoke that whenever it wants a new instance for its own purposes.)
Except that a further complication is that instead of adding the services directly, I'm using reflection to find and register them, so that they just need to be defined to work instead of needing to be explicitly listed out. Originally I wanted to do this completely self-contained, but constructing generic lambda methods based on reflected types just seemed too complicated, so for the moment I've settled with a Register method provided by each type:
class Data1 : DataProvider
{
public static void Register(FooServer server, IEngine engine)
{
server.AddService("Data1", () => new Data1(engine));
}
... (constructor, Dispose, other stuff)
}
var server = new FooServer();
foreach (var type in Utils.GetConcreteTypesWithBase<DataProvider>())
{
var method = type.GetMethod("Register", new[] { typeof(FooServer), typeof(IEngine) });
if (method != null)
{
method.Invoke(null, new object[] { server, engine });
}
// a more ideal approach would be to construct the needed lambda and call
// AddService directly instead of using Register, but my brain fails me.
}
server.Start();
...
server.Dispose();
Needless to say, this is a bit ugly and I'm sure there's a better way to do it. One other thing is that I'm already using Castle Windsor to create the IEngine and a few other things that use it, and I was wondering how to better integrate with that. (Currently I'm just Resolveing the engine at the point where this code needs it -- it's a singleton so lifetimes aren't thorny.)
What I'd really love is a way to use method parameter or constructor injection so that each DataProvider could have a different set of parameters based on their actual dependencies (instead of the union of all dependencies), just like you'd do when everything was under Windsor's control. But again, I'm not sure where to even start. I haven't really used Windsor much beyond the basics.
Note that FooServer, DataProvider and the AddService<T>(string name, Func<T> factory) where T: DataProvider method are in external code and I can't change them. The rest (including the engine) is my code. And again note that I do not create the Data1 instances in my code at all, just a factory lambda that tells the external server how to create them when it wants one.
Following qujck's answer with a few necessary edits resulted in the following code, for posterity:
var container = ...;
var server = new FooServer();
foreach (var type in Utils.GetConcreteTypesWithBase<DataProvider>())
{
var t = type; // necessary due to the lambda capturing
container.Register(Component.For(t).LifestyleTransient());
server.AddService(t.Name, () => {
var service = (DataProvider) container.Resolve(t);
service.Closed += (s, e) => container.Release(service);
return service;
});
}
server.Start();
...
server.Dispose();
This behaves as desired, though I'm still interested in methods to improve it further. (I was curious if there was some way to use Castle's own Classes.FromAssembly... etc syntax to tidy up the discovery and registration of the services, but haven't had much luck working that out.)
You could define lambda's that resolve from the container. This offers the benefits of managing all of your services and their related lifetimes in one place (the container).
You would need some way of establishing the name of each registration - in the example I have registered each service as the name of the type:
[Fact]
public void Configure1()
{
IWindsorContainer container = new WindsorContainer();
var server = new MockFooServer();
container.Register(Component.For<IEngine>().ImplementedBy<Engine>());
foreach (Type type in Utils.GetConcreteTypesWithBase<DataProvider>())
{
container.Register(Component.For(type));
server.AddService(type.Name, () => container.Resolve(type) as DataProvider);
}
var service1 = server.services[typeof(Service1).Name]();
Assert.IsType<Service1>(service1);
}
With a Mock FooServer for the test:
public class MockFooServer
{
public Dictionary<string, Func<DataProvider>> services =
new Dictionary<string, Func<DataProvider>>();
public void AddService<T>(string key, Func<T> factory) where T : DataProvider
{
this.services.Add(key, factory as Func<DataProvider>);
}
}

Microsoft Unity 2, how to register the following?

Right now we have a dll file that contains all the database calls and i can't change it. However i need to call i from my Mvc 3 project. The process to call it is simple, i use the following:
ManageProvider.GetProxy<T>(ident);
T is an interface that i want to get the class back from (its like an IoC of its own) and ident is the user identification class. So by calling
var classReturned = ManageProvider.GetProxy<ICommunity>(new UserIden{ Email = "test#test.com" });
I would get a class back with all the community functions.
Now i want to implement Unity in my Mvc 3 project. The question is, can i somehow add these calls to the dll file through unity?
I want to resolve the call by using:
var classReturned = myContainer.Resolve<ICommunity>(new UserIden{ Email = "test#test.com" });
How can i register this in Unity (or is it even possible) ?
Update:
1) Is it better to call the methods with the email/user ident instead of defining a Dependency property? (ex below)
2) There is a bout 20 or so interfaces in the dll file right now. Should i add them all to the same reposatory? (ex below)
public class ProxyWrapper : IDllRepository
{
[Dependency]
public UserIdent UserIdent { get; set; }
public ICommunity GetCommunity()
{
return ManageProvider.GetProxy<ICommunity>(UserIdent);
}
public IDesktop GetDesktop()
{
return ManageProvider.GetProxy<IDesktop>(UserIdent);
}
}
public interface IDllRepository
{
ICommunity GetCommunity();
IDesktop GetDesktop();
}
Whats the best way and how would i call it from my code?
Does the [Dependency] attribute also fall into the Service Locator anti pattern?
Update 23.05.11
1) Yes, something like that. They contain all the logic that is provided to all the projects that includes the dll file.
Regarding the ManagerProvider. It accepts an interface and returns the class that is mapped to this interface. So for the community, the interface looks like this (removed a lot of calls to keep it short, there is also posts, comments, community create/update etc):
List<CommunityThread> GetThreads(int pStartRowIndex, int pMaximumRows, string pOrderBy, string pSearchExpression);
Guid? CreateThread(string pTitle, string pDescription, string pPostContent);
bool DeleteThread(Guid pThreadId);
List<CommunityThread> GetCommunityUserThreads(Guid pCommunityUserId);
2) What i can't update is how the ManageProvider.GetProxy works. The GetProxy is a class in the dll file that is hardcoded. Here is the part for the community. The class does the same for all the other interfaces as well, if typeof(interface) ... return class.
private static IManageProxy GetProxyForInterface<T>(UserIdent pIdent)
{
....
if (typeof(T).Equals(typeof(ICommunity)))
return new PCommunity();
....
}
3) Once registered using this new wrapper class, i can call it through the following code (MvcUnityContainer is a static class that only has a property called Container):
var c = MvcUnityContainer.Container.Resolve<IBackendRepository>(new PropertyOverride("UserIdent",
new UserIdent()));
Global.asax
IUnityContainer container = InitContainer();
MvcUnityContainer.Container = container;
DependencyResolver.SetResolver(new UnityMvcResolver(container));
The question is, do i need the static class MvcUnityContainer? Is it possible to configure the DependecyResolver to do that for me? Something like (problem is that it doesn't accept the override parameter):
var c = DependencyResolver.Current.GetService<IBackendRepository>(new PropertyOverride("UserIdent", new UserIdent()));
I think you need to hide the creation behind another abstraction, for instance:
public interface ICommunityRepository
{
ICommunity GetByEmailAddress(string address);
}
public class ManageProviderCommunityRepository
: ICommunityRepository
{
public ICommunity GetByEmailAddress(string address)
{
var id = new UserIden { Email = address };
return ManageProvider.GetProxy<ICommunity>(id);
}
}
This will hide both the ManageProvider and the UserIden behind this abstraction, and allows you to replace it later on with something more useful and makes testing easier.
Registration now is very easy:
RegisterType<ICommunityRepository, ManageProviderCommunityRepository>();
Instead of calling myContainer.Resolve (as you do in your example), inject the dependencies in your classes. This prevents you from using the Service Locator anti-pattern.
Perhaps you could do something like this, using the InjectionFactory:
myContainer.RegisterType<ICommunity>(
new InjectionFactory(c => ManageProvider.GetProxy<ICommunity>(new UserIden {Email = "test#test.com"})));
var classReturned = myContainer.Resolve<ICommunity>();
... Though you wouldn't be able to pass the UserIden as a parameter to the Resolve call, so I'm not sure if this is what you want.
To register all the public classes of the assembly you could perhaps iterate over Assembly.GetTypes() and register them in the same way?

Categories

Resources