We are using factory to create an instance of Subscribers. Each subscriber can have its own dependency.
Each subscriber will use constructor injection.
Should I pass dependency into subscribers through Subscriber Factory? Every time adding new dependency in any subscriber will change Subscriber factory?
public interface IMessageSubscriber
{
bool Process(string message)
}
public class MessageSubscriber1 : IMessageSubscriber
{
public bool Process(string message)
{
//Some custom logic
}
}
public class MessageSubscriber2 : IMessageSubscriber
{
public bool Process(string message)
{
//Some custom logic
}
}
public class MessageSubscriberFactory
{
//SubscriberType is enum
public IMessageSubscriber Get(SubscriberType type)
{
if(type == 1)
{
return new MessageSubscriber1();
}
else if(type == 2)
{
return new MessageSubscriber2();
}
}
}
//Main class
public class Process
{
public static void Main(string[] args)
{
MessageSubscriberFactory fac = new MessageSubscriberFactory();
foreach SubscriberType
{
string = "Message";
IMessageSubscriber subscriber = fac.Get(type);
subscriber.Process(message)
}
}
}
One approach would be to use named registrations with a DI/IOC container. This would involve using the container in a service locator fashion (which some people oppose), but I think it could make sense in this case. The example below is pretty crude, but it does give you an approach to handle subscribers with different dependencies without passing them into the factory. I used Unity here and you'd want to wrap the container reference rather than referencing directly, but this gets the point across.
public interface ILowerCaseWriter
{
void Write(string message);
}
public class LowerCaseWriter : ILowerCaseWriter
{
public void Write(string message)
{
Console.WriteLine(message.ToLower());
}
}
public interface IUpperCaseWriter
{
void Write(string message, int number);
}
public class UpperCaseWriter : IUpperCaseWriter
{
public void Write(string message, int number)
{
Console.WriteLine("{0}:{1}", number, message.ToUpper());
}
}
public interface ISubscriber
{
void Write();
}
public class Subscriber1 : ISubscriber
{
private ILowerCaseWriter _writer;
public Subscriber1(ILowerCaseWriter writer)
{
_writer = writer;
}
public void Write()
{
_writer.Write("Using subscriber 1");
}
}
public class Subscriber2 : ISubscriber
{
private IUpperCaseWriter _writer;
public Subscriber2(IUpperCaseWriter writer)
{
_writer = writer;
}
public void Write()
{
_writer.Write("Using subscriber 2", 2);
}
}
public class SubscriberFactory
{
private UnityContainer _container;
public SubscriberFactory()
{
_container = new UnityContainer();
_container.RegisterType<ILowerCaseWriter, LowerCaseWriter>();
_container.RegisterType<IUpperCaseWriter, UpperCaseWriter>();
_container.RegisterType<ISubscriber, Subscriber1>("Subscriber1");
_container.RegisterType<ISubscriber, Subscriber2>("Subscriber2");
}
public ISubscriber GetSubscriber(int type)
{
switch (type)
{
case 1:
return _container.Resolve<ISubscriber>("Subscriber1");
case 2:
return _container.Resolve<ISubscriber>("Subscriber2");
default:
throw new Exception();
}
}
}
class Program
{
private static void Main(string[] args)
{
var factory = new SubscriberFactory();
var subscriber = factory.GetSubscriber(1);
subscriber.Write();
Console.ReadLine();
}
}
Related
I am trying to make a decorator Logging class for two classes of the same interface type, that would take the class and basically override its method step so it could print some extra things. I found this solution really bad because I am reimplementing things that are already implemented but I can't think of a better solution.
public class A :IA
{
private int state = 0;
public void printStep()
{
Console.WriteLine("A state: {0}", state);
}
public bool Step()
{
state++;
return true;
}
public void Run()
{
for (int i = 0; i < 5; ++i)
{
Step();
}
}
}
public class B : IA
{
private double state = 0.0;
public void printStep()
{
Console.WriteLine("B state: {0}", state);
}
public bool Step()
{
state+= 0.1;
return true;
}
public void Run()
{
for (int i = 0; i < 4; ++i)
{
Step();
}
}
}
public interface IA
{
void printStep();
bool Step();
void Run();
}
public class Logger
{
private IA ia;
public Logger(IA ia)
{
this.ia = ia;
}
public void Run() //Don't like this method especially because it shouldn't reimplement the run methods again
{
if (ia.GetType() == typeof(A))
{
for (int i = 0; i < 5; ++i)
{
ia.printStep();
ia.Step();
}
}
else
{
for (int i = 0; i < 4; ++i)
{
ia.printStep();
ia.Step();
}
}
}
}
Any ideas how to do this?
EDIT: what I would like to do is something like this
public override bool Step()
{
var ret = base.Step();
base.printStep();
return ret;
}
EDIT 2: I need to call the original Run method that would be calling an updated Step method with the added logging. Expected behavior from this simple example would be Logger of class A would print symbol A 5 times and Logger of class B would print symbol B 4 times.
EDIT 3: Why I am trying to do this kind of behavior? What I felt like is having two classes A and B that would be fully working without writing any information on its own. The Logger should take either of them and log every state that would usually change after each step. So I would get a perfect information. I could play with something like adding a boolean variable logging in the A and B classes but it just doesn't feel right.
public class A :IA
{
...
public bool Step()
{
if (logging) printStep();
state++;
return true;
}
...
EDIT 5: Changed the initial code so it makes more sense.
Use:
var a = new A();
a.Run();
var b = new B();
b.Run();
var loggerA = new Logger(a);
loggerA.Run();
var loggerB = new Logger(b);
loggerB.Run();
Expected output:
A state: 5
A state: 6
A state: 7
A state: 8
A state: 9
B state: 0.4
B state: 0.5
B state: 0.6
B state: 0.7
If you want the Logger class to implement the Decorator pattern, it must implement the same interface as the "decorated" classes (not just to encapsulate them as in your snippet).
By doing so you'll be able to achieve the desired behavior (similar to the one in your EDIT).
EDIT:
Assuming that this is the responsibility of the Logger to log something, IA doesn't have to contain the printStep() method.
Thus we have:
public interface IA
{
bool Step();
}
public class A : IA
{
public bool Step()
{
return true;
}
}
public class B : IA
{
public bool Step()
{
return true;
}
}
public class Logger : IA
{
private readonly IA _decorated;
public Logger(IA decorated)
{
_decorated = decorated;
}
public bool Step()
{
Console.WriteLine("Before Step...");
_decorated.Step();
Console.WriteLine("Step completed.");
}
}
When instantiating the Logger you need to pass the object you want to decorate
IA notDecorated = new A();
IA decorated = new Logger(notDecorated);
If you want to get rid of the shared functionality in A and B you can make an abstract class. Implement the shared functionality here and make the remaining methods abstract. If you strictly want to use the decorator pattern you could make an interface for the abstract class.
public class A : AbstractA
{
public override void printStep()
{
Console.WriteLine("A");
}
public override void Run()
{
base.Run();
for (int i = 0; i < 5; ++i)
{
Step();
}
}
}
public class B : AbstractA
{
public override void printStep()
{
Console.WriteLine("B");
}
public override void Run()
{
base.Run();
for (int i = 0; i < 4; ++i)
{
Step();
}
}
}
public abstract class AbstractA : IA
{
public abstract void printStep();
public virtual bool Step()
{
return true;
}
public virtual void Run()
{
printStep();
}
}
public interface IA
{
void printStep();
bool Step();
void Run();
}
public class Logger
{
private IA ia;
public Logger(IA ia)
{
this.ia = ia;
}
void Run()
{
ia.Run();
}
}
If there's not a reason for other objects to be calling Step() directly it shouldn't be part of the interface. However, since I think you're making classes that may be mostly similar in shape but potentially very different in implementation, I don't think decorating these classes will get you what you want. I think it makes more sense to just add in logging where it's needed.
I included a toy example of what a modern logging framework (like NLog) does for you. In my example, you can change whether or not you have logging by passing in a different logging implementation. In a real framework, you have different levels of logging that you can configure so that you can turn off logging completely or only log more important information.
public class A : IA
{
private readonly ILog logger;
public B(ILog logger)
{
this.logger = logger;
}
private bool Step()
{
// some logic
logger.Info("Something specific here.")
// more logic
return true;
}
public void Run()
{
for (int i = 0; i < 5; ++i)
{
logger.Info("A");
Step();
}
}
}
public class B : IA
{
private readonly ILog logger;
public B(ILog logger)
{
this.logger = logger;
}
private bool Step()
{
return true;
}
public void Run()
{
for (int i = 0; i < 4; ++i)
{
logger.Info("B");
Step();
}
}
}
public interface IA
{
void Run();
}
public interface ILog
{
void Info(string message);
}
public class ConsoleLogger : ILog
{
public void Info(string message)
{
Console.WriteLine(message);
}
}
public class NoopLogger : ILog
{
public void Info(string message)
{
}
}
Then when you instantiate your classes, you can pass in whatever logger you need.
var noopLogger = new NoopLogger();
var a = new A(noopLogger);
a.Run();
var b = new B(noopLogger);
b.Run();
var consoleLogger = new ConsoleLogger();
a = new A(consoleLogger);
a.Run();
b = new B(consoleLogger);
b.Run();
I have N validators on my aplication but a client doesn't use all validators, I got by procedure all classes that my current client will need to instantiate.
My Business layer:
public class MyClass
{
public void MyMethod(int idClient)
{
//This array is returned by a procedure passing idClient
string[] validatorsName = { "ValidatorName", "ValidatorName2" };
foreach (string name in validatorsName)
{
IValidator validator = (IValidator)Activator.CreateInstance(Type.GetType(name));
//Error. I need pass the INameDB;
validator.Process();
}
}
}
My Interface:
public interface IValidator
{
void Process();
}
The Validators:
public class ValidatorName : IValidator
{
INameDB nameDB;
public ValidatorName(INameDB nameDB)
{
this.nameDB = nameDB;
}
public void Process()
{
nameDB.AnyThing(pedidoId);
}
}
public class ValidatorName2 : IValidator
{
INameDB2 nameDB;
public ValidatorName(INameDB2 nameDB)
{
this.nameDB = nameDB;
}
public void Process()
{
nameDB.AnyThing2(pedidoId);
}
}
public class ValidatorName3 : IValidator
{
INameDB2 nameDB;
public ValidatorName(INameDB2 nameDB)
{
this.nameDB = nameDB;
}
public void Process()
{
nameDB.AnyThing2(pedidoId);
}
}
On Global, I could register all validators and with the IList<IValidator>, so I would remove from the list the validators that I will not need.
string[] validatorsName = { "ValidatorName", "ValidatorName2" };
validators = validators .Where(p => validatorsName .Contains(p.GetType().Name)).ToList();
but I have a lot of classes, it would register this no need.
My Global:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<NameDB>().As<INameDB>();
builder.RegisterType<NameDB2>().As<INameDB2>();
//builder.RegisterType<ValidatorName1>().As<IValidator>();
//builder.RegisterType<ValidatorName2>().As<IValidator>();
//builder.RegisterType<ValidatorName3>().As<IValidator>();
AutofacHostFactory.Container = builder.Build();
//AutofacHostFactory.Container.Resolve<IList<IValidator>>();
}
}
My question is how can I detect the interface INameDB or INameDB2, get the instance on Autofac and use on Activator.CreateInstance?
Thanks.
After some days, I could code the solution:
My main class, I create a method to injection the validators list:
public class MyClass
{
private IList<IValidator> listValidators;
public void MyMethod(int idClient)
{
ExecuteValidations(idClient);
}
private void ValidatorInjection(int idClient)
{
listValidators = new List<IValidator>();
//This array is returned by a procedure passing idClient
string[] validatorsName = { "ValidatorName", "ValidatorName2" };
foreach (string name in validatorsName)
{
IValidator validador = (IValidator)Activator.CreateInstance(Type.GetType(name));
listValidators.Add(validador);
}
}
private void ExecuteValidations(int idClient)
{
ValidatorInjection(idClient);
RunValidatorsList();
}
private void RunValidatorsList()
{
foreach (var validator in listValidators)
{
validator.Process();
}
}
}
My validators, I needed get the interface database instance on container with INameDB2 db = AutofacHostFactory.Container.Resolve<INameDB2>();:
public class ValidatorName : IValidator
{
public void Process()
{
INameDB db = AutofacHostFactory.Container.Resolve<INameDB>();
db.AnyThing(pedidoId);
}
}
public class ValidatorName2 : IValidator
{
public void Process()
{
INameDB2 db = AutofacHostFactory.Container.Resolve<INameDB2>();
db.AnyThing2(pedidoId);
}
}
public class ValidatorName3 : IValidator
{
public void Process()
{
INameDB2 db = AutofacHostFactory.Container.Resolve<INameDB2>();
db.AnyThing2(pedidoId);
}
}
On Global, I did a way that I don't need add line to register a new class that IValidator implement:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<NameDB>().As<INameDB>();
builder.RegisterType<NameDB2>().As<INameDB2>();
string assembly = "MY_ASSEMBLY";
builder.RegisterAssemblyTypes(Assembly.Load(assembly)).Where(t => t.IsAssignableTo<IValidator>()).AsImplementedInterfaces();
AutofacHostFactory.Container = builder.Build();
}
}
I have an interface IInterface and it looks something like below -
public interface IInterface
{
void SomeMethod1();
void SomeMethod2();
void SomeMethod3();
.
.
.
}
One of the implementations is something like -
public class Implementation : IInterface
{
private Object obj;
public Implementation(Object obj)
{
this.obj = obj;
// Do Something
}
public void SomeMethod1()
{
lock(obj)
{
// Do Something
}
}
public void SomeMethod2()
{
// Do Something
}
public void SomeMethod3()
{
lock(obj)
{
// Do Something
}
}
.
.
.
}
How to pass a static readonly instance of type Object while registering Implementation class with type IInterface via unity configuration?
My preferred approach is probably to create a factory for creating IInterfaces
public interface IInterface
{
void SomeMethod1();
}
public interface IInterfaceFactory
{
IInterface CreateInterface();
}
public class StandardInterfaceFactory : IInterfaceFactory
{
// Define your static lock object here. Other customers
// can define their own IInterfaceFactory to use a
// different lock object.
private static readonly object lockObject = new object();
public IInterface CreateInterface()
{
return new StandardInterface(lockObject);
}
}
public class StandardInterface : IInterface
{
private readonly object lockObject;
public StandardInterface(object lockObject)
{
this.lockObject = lockObject;
}
public void SomeMethod1()
{
lock (this.lockObject)
{
Console.WriteLine("I've locked on " + lockObject);
}
}
}
Your unity configuration and client code will then look like this.
void Main()
{
IUnityContainer container = new UnityContainer();
// This mapping can be done trivially in XML configuration.
// Left as an exercise for the reader :)
container.RegisterType<IInterfaceFactory, StandardInterfaceFactory>();
IInterfaceFactory factory = container.Resolve<IInterfaceFactory>();
IInterface myInterface = factory.CreateInterface();
myInterface.SomeMethod1();
}
I'm trying out an example of using Domain Events to notify of when something has happened in a system (borrowed from here and here).
I'm really close to getting the code working how I want, however, I've hit a bit of a brick wall. Here is my DomainEvents class:
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T : IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback); // <---- Problem here, since I can't add callback to the collection.
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (var action in Actions)
{
if (action is IEventHandler<T>)
{
((IEventHandler<T>)action).Handle(args);
}
}
}
The above won't compile because Actions.Add cannot accept callback since it's a IEventHandler<T> type rather then a IEventHandler<IDomainEvent> type. Here's some more code to clarify.
This is called from my console application:
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
CustomerHasUnpaidDuesEventHandler implements IEventHandler<CustomerHasUnpaidDuesEvent>, where CustomerHasUnpaidDuesEvent implements IDomainEvent.
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
This is what I don't get - if CustomerHasUnpaidDuesEvent implements IDomainEvent, then why is the call to Actions.Add failing? How can I resolve this?
EDIT:
To make things clearer, here is entire code for my test app:
class Program
{
static void Main()
{
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
var c = new Customer();
c.EmailAddress = "test#dfsdf.com";
c.CheckUnpaidDues();
}
}
public interface IEventHandler<in T> where T : IDomainEvent
{
void Handle(T args);
}
public interface IEmailSender
{
void SendEmail(string emailAddress);
}
public interface IDomainEvent
{
}
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T: IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (IEventHandler<T> action in Actions)
{
(action).Handle(args);
}
}
}
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public bool HasUnpaidDues { get; set; }
public void CheckUnpaidDues()
{
HasUnpaidDues = true;
DomainEvents.Raise(new CustomerHasUnpaidDuesEvent(this));
}
}
Cheers.
Jas.
There is no need for your Register method to be generic:
public static void Register(IEventHandler<IDomainEvent> callback)
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
Edit:
The problem is that in order to have IEventHandler<CustomerHasUnpaidDuesEvent> to be in the list of IEventHandler<IDomainEvent>s, we need T to be a covariant template parameter in IEventHandler<T> (which is declared as IEventHandler<out T>). However in order to allow the function Handle(T arg), we need T to be contravariant. So strictly this way won't work. Imagine: if we really could insert an IEventHandler<CustomerHasUnpaidDuesEvent> into a list of IEventHandler<IDomainEvent>s, than someone might try to call Handle with the argument of some type which derives from IDomainEvent but is not a CustomerHasUnpaidDuesEvent! This should be impossible to do.
The solution is that we don't need the exact type at Register, so we can keep a reference to a generic base interface. The implementation is here: http://ideone.com/9glmQ
Old answer is not valid, kept below for consistency.
Maybe you need to declare IEventHandler to accept T as a covariant type?
interface IEventHandler<in T> where T: IDomainEvent
{
void Handle();
// ...
}
Edit: surely CustomerHasUnpaidDuesEvent is an IDomainEvent, but you need IEventHandler<CustomerHasUnpaidDuesEvent> to be a IEventHandler<IDomainEvent>. This is exactly what covariance does. In order to allow that, your template parameter in IEventhandler must be declared covariant (<in T> instead of just <T>).
Why doesn't DoIt() method call get intercepted? Should I use something other than InterfaceInterceptor to intercept the DoIt() method? How would you do it?
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
namespace UnityTest
{
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<ILogger, Logger>();
container.Configure<Interception>().SetInterceptorFor<ILogger>(new InterfaceInterceptor());
var logger = container.Resolve<ILogger>();
logger.Write("World.");
Console.ReadKey();
}
}
public interface ILogger
{
void Write(string message);
[Test]
void DoIt(string message);
}
public class Logger : ILogger
{
public void Write(string message)
{
DoIt(message);
}
public void DoIt(string message)
{
Console.Write(message);
}
}
public class TestAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new TestHandler();
}
}
public class TestHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.Write("Hello, ");
return getNext()(input, getNext);
}
}
}
You need to apply the [Test] attribute to ILogger.Write instead of DoIt. The way interception works is to create a transparent proxy which then passes control to any handlers before the target method. The problem with your current setup is that DoIt is called by the logger instance itself, so there is no way for the proxy to intercept the call. In other words, you can only intercept methods called directly on an interface when using interception.