My app relies on multiple event bus objects which are basic publish/subscribe notification model (http://caliburn.codeplex.com/wikipage?title=The%20Event%20Aggregator).
What I want to do is share certain an instance of aggregators with a groups of components. Say component I have a single event bus that's shared between component A, B, and C, and then another event bus that's shared between D,E,F.
I essentially want to declare the event busses as singleton and inject them based on some criteria. I kinda wanna avoid subtyping the event busses just for the purposes of distinguishing resolution.
I've used Google Guice IoC in java which allows metadata resolution for a parameter. Aka in java it allowed me to something equivalent to this.
Example:
public A([SpecialUseAggregator]IEventAggregator something)
public B([SpecialUseAggregator]IEventAggregator something)
public E([AnotherUseAggregator]IEventAggregator something)
public F([AnotherUseAggregator]IEventAggregator something)
Any suggestions?
Autofac does not have/use attributes for the registration. One solution is to use the Named/Keyed registration feature.
So you need to need to register you two EventAggreator with different names/keys and when registering your consumer types A,B, etc you can use the WithParameter to tell Autofac which IEventAggreator it should use for the given instance:
var contianerBuilder = new ContainerBuilder();
contianerBuilder.Register(c => CreateAndConfigureSpecialEventAggregator())
.Named<IEventAggreator>("SpecialUseAggregator");
contianerBuilder.Register(c => CreateAndConfigureAnotherUseAggregator())
.Named<IEventAggreator>("AnotherUseAggregator");
contianerBuilder.RegisterType<A>).AsSelf()
.WithParameter(ResolvedParameter
.ForNamed<IEventAggreator>("SpecialUseAggregator"));
contianerBuilder.RegisterType<B>().AsSelf()
.WithParameter(ResolvedParameter
.ForNamed<IEventAggreator>("SpecialUseAggregator"));
contianerBuilder.RegisterType<C>).AsSelf()
.WithParameter(ResolvedParameter
.ForNamed<IEventAggreator>("AnotherUseAggregator"));
contianerBuilder.RegisterType<D>().AsSelf()
.WithParameter(ResolvedParameter
.ForNamed<IEventAggreator>("AnotherUseAggregator"));
var container = contianerBuilder.Build();
I you still would like to use attributes then you can do it with Autofac because it has all the required extension points it just requires some more code to teach Autofac about your attribute and use it correctly.
If you are registering your types with scanning you cannot use the easily use the WithParameter registration however you use the Metadata facility in Autofac:
Just create an attribute which will hold your EventAggreator key:
public class EventAggrAttribute : Attribute
{
public string Key { get; set; }
public EventAggrAttribute(string key)
{
Key = key;
}
}
And attribute your classes:
[EventAggrAttribute("SpecialUseAggregator")]
public class AViewModel
{
public AViewModel(IEventAggreator eventAggreator)
{
}
}
Then when you do the scanning you need to use the WithMetadataFrom to register the metadata:
contianerBuilder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.EndsWith("ViewModel"))
.OnPreparing(Method)
.WithMetadataFrom<EventAggrAttribute>();
And finally you need the OnPreparing event where you do the metadata based resolution:
private void Method(PreparingEventArgs obj)
{
// Metadata["Key"] is coming from the EventAggrAttribute.Key
var key = obj.Component.Metadata["Key"].ToString();
ResolvedParameter resolvedParameter =
ResolvedParameter.ForNamed<IEventAggreator>();
obj.Parameters = new List<Parameter>() { resolvedParameter};
}
Here is gist of a working unit test.
Related
in this tutorial about the EventCloud example app:
https://aspnetboilerplate.com/Pages/Documents/Articles/Developing-MultiTenant-SaaS-ASP.NET-CORE-Angular/index.html
the text states: the creation of a new entity must be done using the static method "Create" in the "Event" class (not using "new Entity(....)")
1) so my first question is: which design pattern is this? Factory? Builder? other?
[Table("AppEvents")]
public class Event : FullAuditedEntity<Guid>, IMustHaveTenant
{
......
....
...
/// <summary>
/// We don't make constructor public and forcing to create events using <see cref="Create"/> method.
/// But constructor can not be private since it's used by EntityFramework.
/// Thats why we did it protected.
/// </summary>
protected Event()
{
}
public static Event Create(int tenantId, string title, DateTime date, string description = null, int maxRegistrationCount = 0)
{
var #event = new Event
{
Id = Guid.NewGuid(),
TenantId = tenantId,
Title = title,
Description = description,
MaxRegistrationCount = maxRegistrationCount
};
#event.SetDate(date);
#event.Registrations = new Collection<EventRegistration>();
return #event;
}
....
...
2) the second question:
than the article says...
Event Manager .... All Event operations should be executed using this class... (EventManager)
ok, the CreateAsync method call the repository insert method, is the static "Event.Create" internaly called from the repository insert method? if yes, could you indicate me the point in the abp source code?
or is it an internal matter of EntityFramework?
public class EventManager : IEventManager
{
......
....
..
public async Task CreateAsync(Event #event)
{
await _eventRepository.InsertAsync(#event);
}
Here are my answers:
1-) Event is being created with a static factory method. There are 2 ways to create an entity in Domain Driven Design.
Creating with static factory methods: It's a convenient way of creating business entities. And this method is being used in EventCloud. The only downside of this method is it's static! If your entity is holding state it's not good for testability. But there are 3 advantages of this approach;
They have names: for example Event.CreatePublicEvent(), Create.PrivateEvent()
They can cache: You can cache them in a private static HashSet or Dictionary.
They can subtype.
Creating with a constructor: If you have only one constructor then creating an object through its public constructor is the most convenient approach in Domain Driven Design. As long as you make parameterless constructor protected or private. Besides, an entity should be responsible for its own data integrity and validity so you have to set all business related public properties as private setter and you should allow them to change through public methods.
Further information, see https://www.yegor256.com/2017/11/14/static-factory-methods.html
2-) EventManager is a domain service that is used for business logic. And Event.Create() is being used in the EventAppService class. Click here to see where exactly is being executed. Even Event.Create() method consists of a single line of code but it's open for extension.
I hope that will be useful ;)
Happy coding...
With Autofac, what is the proper way to register types or declare dependencies for this type of circular graph?
public interface IComponent
{
void DoSomething();
}
public class AComponent: IComponent
{
...
}
public class BComponent: IComponent
{
...
}
public class CompositeComponent: IComponent
{
public CompositeComponent(IEnumerable<IComponent> components)
{
this.components = components;
}
public void DoSomething()
{
foreach(var component in components)
component.DoSomething();
}
}
The end goal would be that CompositeComponent be the default registration of IComponent and simply pass down calls to all other implementations.
I am gathering that the intent of the question is that you have some implementations of IComponent and you have some sort of CompositeComponent that also implements IComponent. CompositeComponent needs all of the registered IComponent instances except itself otherwise it creates a circular dependency.
This whole thing overlaps pretty heavily with one of our FAQs: "How do I pick a service implementation by context?"
You have some options. In order of my personal recommendation:
Option 1: Redesign the Interfaces
There are actually two concepts going on here - the notion of an individual handler and the notion of a thing that aggregates a set of individual handlers.
Using less generic terms, you might have an IMessageHandler interface and then something that passes a message through the set of all IMessageHandler implementations, but that thing that aggregates the handlers and deals with errors and ensuring the message is handled only by the right handler and all that... that isn't, itself, also a message handler. It's a message processor. So you'd actually have two different interfaces, even if the methods on the interface look the same - IMessageHandler and IMessageProcessor.
Back in your generic component terms, that'd mean you have IComponent like you do now, but you'd also add an IComponentManager interface. CompositeComponent would change to implement that.
public interface IComponentManager
{
void DoSomething();
}
public class ComponentManager : IComponentManager
{
public ComponentManager(IEnumerable<IComponent> components)
{
this.components = components;
}
public void DoSomething()
{
foreach(var component in components)
component.DoSomething();
}
}
Option 2: Use Keyed Services
If you won't (or can't) redesign, you can "flag" which registrations should contribute to the composite by using service keys. When you register the composite, don't use a key... but do specify that the parameter you want for the constructor should resolve from the keyed contributors.
builder.RegisterType<AComponent>()
.Keyed<IComponent>("contributor");
builder.RegisterType<BComponent>()
.Keyed<IComponent>("contributor");
builder.RegisterType<CompositeComponent>()
.As<IComponent>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.Name == "components",
(pi, ctx) => ctx.ResolveKeyed<IEnumerable<IComponent>>("contributor")));
When you resolve IComponent without providing a key, you'll get the CompositeComponent since it's the only one that was registered that way.
Option 3: Use Lambdas
If you know up front the set of components that should go into the composite, you could just build that up in a lambda and not over-DI the whole thing.
builder.Register(ctx =>
{
var components = new IComponent[]
{
new AComponent(),
new BComponent()
};
return new CompositeComponent(components);
}).As<IComponent>();
It's more manual, but it's also very clear. You could resolve individual constructor parameters for AComponent and BComponent using the ctx lambda parameter if needed.
What is the difference between factory and pipeline design patterns?
I am asking because I need making classes, each of which has a method that will transform textual data in a certain way.
I have other classes whose data needs to be transformed. However, the order and selection of the transformations depends on (and only on) which base class from which these classes inherit.
Is this somehow related pipeline and/or a factory pattern?
Factory creates objects without exposing the instantiation logic to the client and refers to the newly created object through a common interface. So, goal is to make client completely unaware of what concrete type of product it uses and how that instance created.
public interface IFactory // used by clients
{
IProduct CreateProduct();
}
public class FooFactory : IFactory
{
public IProduct CreateProduct()
{
// create new instance of FooProduct
// setup something
// setup something else
// return it
}
}
All creation details are encapsulated. You can create instance via new() call. Or you can clone some existing sample FooProduct. You can skip setup. Or you can read some data from database before. Anything.
Here we go to Pipeline. Pipeline purpose is to divide a larger processing task into a sequence of smaller, independent processing steps (Filters). If creation of your objects is a large task AND setup steps are independent, you can use pipeline for setup inside factory. But instantiation step definitely not independent in this case. It mast occur prior to other steps.
So, you can provide Filters (i.e. Pipeline) to setup your product:
public class BarFilter : IFilter
{
private IFilter _next;
public IProduct Setup(IProduct product)
{
// do Bar setup
if (_next == null)
return product;
return _next.Setup(product);
}
}
public abstract class ProductFactory : IProductFactory
{
protected IFilter _filter;
public IProduct CreateProduct()
{
IProduct product = InstantiateProduct();
if (_filter == null)
return product;
return _filter.Setup(product);
}
protected abstract IProduct InstantiateProduct();
}
And in concrete factories you can setup custom set of filters for your setup pipeline.
Factory is responsible for creating objects:
ICar volvo = CarFactory.BuildVolvo();
ICar bmw = CarFactory.BuildBMW();
IBook pdfBook = BookFactory.CreatePDFBook();
IBook htmlBook = BookFactory.CreateHTMLBook();
Pipeline will help you to separate processing into smaller tasks:
var searchQuery = new SearchQuery();
searchQuery.FilterByCategories(categoryCriteria);
searchQuery.FilterByDate(dateCriteria);
searchQuery.FilterByAuthor(authorCriteria);
There is also a linear pipeline and non-linear pipeline. Linear pipeline would require us to filter by category, then by date and then by author. Non-linear pipeline would allow us to run these simultaneously or in any order.
This article explains it quite well:
http://www.cise.ufl.edu/research/ParallelPatterns/PatternLanguage/AlgorithmStructure/Pipeline.htm
This is more like a conceptual question. When to use Model Binding (in ASP.NET MVC Framework) and when to inject objects using IoC (lets say Autofac here) ?
One specific scenario is like lets say, I have the following action method
public ActionResult EditProfile(string UserId)
{
// get user object from repository using the the UserId
// edit profile
// save changes
// return feedback
}
In the above scenario, is it possible to inject a user object to action method such that it automatically gets the user object using the UserId ? The resulting signature being:
public ActionResult EditProfile(UserProfile userObj) //userObj injected *somehow* to automatically retreive the object from repo using UserId ?
Sorry if it all doesn't makes sense. It`s my first time using IoC.
EDIT:
This is the way to do it > http://buildstarted.com/2010/09/12/custom-model-binders-in-mvc-3-with-imodelbinder/
You can do what you need using a custom action filter. By overriding OnActionExecuting, we have access to the route data, and the action parameters of the action that will be executed. Given:
public class BindUserProfileAttribute : ActionFilterAttribute
{
public override OnActionExecuting(FilterContext filterContext)
{
string id = (string)filterContext.RouteData.Values["UserId"];
var model = new UserProfile { Id = id };
filtextContext.ActionParameters["userObj"] = model;
}
}
This attribute allows us to create the parameters that will be passed into the action, so we can load the user object at this point.
[BindUserProfile]
public ActionResult EditProfile(UserProfile userObj)
{
}
You'll probably need to get specific with your routes:
routes.MapRoute(
"EditProfile",
"Account/EditProfile/{UserId}",
new { controller = "Account", action = "EditProfile" });
In MVC3 we get access to the new IDepedencyResolver interface, which allows us to perform IoC/SL using whatever IoC container or service locator we want, so we can push a service like a IUserProfileFactory into your filter, to then be able to create your UserProfile instance.
Hope that helps?
Model binding is used for your data. Dependency injection is used for your business logic.
I need to add some extension points to our existing code, and I've been looking at MEF as a possible solution. We have an IRandomNumberGenerator interface, with a default implementation (ConcreteRNG) that we would like to be swappable. This sounds like an ideal scenario for MEF, but I've been having problems with the way we instantiate the random number generators. Our current code looks like:
public class Consumer
{
private List<IRandomNumberGenerator> generators;
private List<double> seeds;
public Consumer()
{
generators = new List<IRandomNumberGenerator>();
seeds = new List<double>(new[] {1.0, 2.0, 3.0});
foreach(var seed in seeds)
{
generators.Add(new ConcreteRNG(seed));
}
}
}
In other words, the consumer is responsible for instantiating the RNGs it needs, including providing the seed that each instance requires.
What I'd like to do is to have the concrete RNG implementation discovered and instantiated by MEF (using the DirectoryCatalog). I'm not sure how to achieve this. I could expose a Generators property and mark it as an [Import], but how do I provide the required seeds?
Is there some other approach I am missing?
Currently there isn't a direct way to do this in MEF but the MEF team is considering support for this in v.Next. You essentially want to create multiple instances of the same implementation which is traditially done using a Factory pattern. So one approach you could use is something like:
public interface IRandomNumberGeneratorFactory
{
IRandomNumberGenerator CreateGenerator(int seed);
}
[Export(typeof(IRandomNumberGeneratorFactory))]
public class ConcreateRNGFactory : IRandomNumberGeneratorFactory
{
public IRandomNumberGenerator CreateGenerator(int seed)
{
return new ConcreateRNG(seed);
}
}
public class Consumer
{
[Import(typeof(IRandomNumberGeneratorFactory))]
private IRandomNumberGeneratorFactory generatorFactory;
private List<IRandomNumberGenerator> generators;
private List<double> seeds;
public Consumer()
{
generators = new List<IRandomNumberGenerator>();
seeds = new List<double>(new[] {1.0, 2.0, 3.0});
foreach(var seed in seeds)
{
generators.Add(generatorFactory.CreateGenerator(seed));
}
}
}
MEF preview 8 has experimental support for this, though it is not yet included in System.ComponentModel.Composition.dll. See this blog post for more information.
You'll have to download the MEF sources and build the solution. In the Samples\DynamicInstantiation folder you'll find the assembly Microsoft.ComponentModel.Composition.DynamicInstantiation.dll. Add a reference to this assembly and add a dynamic instantiation provider to your container like this:
var catalog = new DirectoryCatalog(".");
var dynamicInstantiationProvider = new DynamicInstantiationProvider();
var container = new CompositionContainer(catalog, dynamicInstantiationProvider);
dynamicInstantiationProvider.SourceProvider = container;
Now your parts will be able to import a PartCreator<Foo> if they need to dynamically create Foo parts. The advantage over writing your own factory class is that this will transparently take care of the imports of Foo, and the imports' imports, etcetera.
edit:
in MEF Preview 9 PartCreator was renamed to ExportFactory but it is only included in the silverlight edition.
in MEF 2 Preview 2, ExportFactory became included for the desktop edition. So ExportFactory will probably be part of the next .NET framework version after .NET 4.0.
I believe this is what the Lazy Exports feature is for. From that page:
[Import]
public Export<IMessageSender> Sender { get; set; }
In this case you are opt-in for delaying this instantiation until you actually need the implementation instance. In order to request the instance, use the method [Export.GetExportedObject()]. Please note that this method will never act as a factory of implementations of T, so calling it multiple times will return the same object instance returned on the first call.