I am reshaping an entire system that does not use base classes and base interfaces.
My idea to do so is to extract all the common methods to a base classes and base interfaces.
So basically, we would have:
A base class SomeClassBase implementing an interface ISomeClassBase
A derived class SomeClassDerived implementing ISomeClassDerived (this interface deriving from ISomeClassBase)
Now the problem, how can I instantiate "_mySession" in the derived class (which has a different cast than in the base class), while preserving all the methods from the base class:
public class SomeClassBase : ISomeClassBase
{
public IMySessionBase _mySession = MySession.Instance();
public SomeClassBase ()
{
_mySession.connect(); // Needed??
}
public void doSomething()
{
_mySession.doSomething();
}
}
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
public IMySessionDerived _mySession = MySession.Instance();
public SomeClassDerived ()
{
_mySession.connect();
}
public void doSomethingElse()
{
_mySession.doSomethingElse();
}
}
One more thing, IMySessionDerived implements IMySessionBase.
Do not redefine _mySession Let it come from base class.
However in you Derived class you can still reassign.
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
public SomeClassDerived ()
{
_mySession = MySession.Instance(); //Declaration comes from base class automatically
_mySession.connect();
}
public void doSomethingElse()
{
_mySession.doSomethingElse();
}
}
If your IMySessionBase and IMySessionDerived are following Hierarchy, it should work. But in some rare cases, You might end up getting into a DoubleDispatchProblem.
As Pointed out in commens, If you want to do something from IMySessionDerived you can add a Property.
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
IMySessionDerived _derivedSessionAccessor=> _mySession as IMySessionDerived;
}
Update: To fix the exact design problem here,
Instead of deriving from the base class, have it as a field. And inherit from interface. So Instead of doing above approach,
do like,
public class SomeClassBase : ISomeClassBase
{
public IMySessionBase _mySession ;
public SomeClassBase ( IMySessionBase session)
{
_mySession=session;
_mySession.connect(); // Needed??
}
public void doSomething()
{
_mySession.doSomething();
}
}
public class SomeClassDerived : , ISomeClassDerived
{
public IMySessionDerived _mySession = MySession.Instance();
private SomeClassBase _baseClassInstance;
public SomeClassDerived ()
{
_baseClassInstance=new SomeClassBase(_mySession);
//_mySession.connect();
}
public void doSomethingElse()
{
_baseClassInstance.doSomethingElse();
}
}
Pasting #Selvin answer instead of the link buried in the comments:
The trick here is to use the keyword "base()"
using System;
using System.Runtime.CompilerServices;
public class Program
{
public static void Main()
{
var o1 = new O1();
o1.DS1();
var o2 = new O2();
o2.DS1();
o2.DS2();
}
public class Session1
{
protected readonly Type ownerType;
public Session1(Type type)
{
ownerType = type;
}
public virtual void DS1([CallerMemberName] string functionName = "")
{
Console.WriteLine(ownerType.Name + ":" + GetType().Name + ":" + functionName);
}
}
public class Session2 : Session1
{
public Session2(Type type):base(type) { }
public virtual void DS2([CallerMemberName] string functionName = "")
{
Console.WriteLine(ownerType.Name + ":" + GetType().Name + ":" + functionName);
}
}
public class O1
{
private readonly Session1 t;
public O1() : this(new Session1(typeof(O1))) { }
protected O1(Session1 t)
{
this.t = t;
}
public void DS1()
{
t.DS1();
}
}
public class O2 : O1
{
private readonly Session2 t;
public O2() : this(new Session2(typeof(O2))) { }
protected O2(Session2 t) : base(t)
{
this.t = t;
}
public void DS2()
{
t.DS2();
}
}
}
I have this class where I'm trying to inject a list of qualifying objects:
public class BlingDispatcher : IBlingDispatcher
{
readonly IEnumerable<IDomainEventHandler> _domainEventHandlers;
#region IBlingDispatcher Members
public BlingDispatcher(IEnumerable<IDomainEventHandler> domainEventHandlers)
{
_domainEventHandlers = domainEventHandlers;
}
}
Classes like this get injected here and work great:
public class NotifyFrontEndSomethingHappened : IDomainEventHandler<SomethingHappened>
{
private readonly IFrontEndNotifier _frontEndNotifier;
public NotifyFrontEndAfterSomethingHappened(IFrontEndNotifier frontEndNotifier)
{
_frontEndNotifier = frontEndNotifier;
}
}
Classes like this do not:
public class NotifyFrontEndAfterEvent : IDomainEventHandler<SomethingHappened>,
IDomainEventHandler<SomethingElseHappened>,
IDomainEventHandler<MoreThingsHappened>,
IDomainEventHandler<AndYetMoreThings>
{
readonly IFrontEndNotifier _frontEndNotifier;
public void Handle(SomethingHappened #event)
{
_frontEndNotifier.Notify(#event, #event.CommanderId);
}
...
}
How can I get classes with multiple interfaces to be injected by autofac as well?
EDIT
More information:
public interface IDomainEventHandler
{
}
public interface IDomainEventHandler<in T> : IBlingHandler<T>, IDomainEventHandler
{
}
public interface IBlingHandler<in T>
{
void Handle(T #event);
}
Registering like this in bootstapper:
container.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(x => x.GetInterfaces().Any(i => i.Name.StartsWith("IBlingHandler")))
.AsImplementedInterfaces();
I have an abstract class called EntityTypeTransform with a single abstract method designed to hold a Func delegate that converts an IDataRecord into an instance of T.
public abstract class EntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransform();
}
An implementation of that class might look like (does look like) this:
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransform()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
Now I want to keep an instance of each of these classes in a generic Dictionary, something like:
Dictionary<Type, EntityTypeTransform<T>>
But this doesn't work because (for example) an instance of EntityTypeTransform Of Task is not the same as an instance of EntityTypeTransform Of TaskParameter.
Can anyone help me out?
Edit: I should add that the Type key = typeof(T)
Actually, you don't need to use a dictionary at all! You can use the fact that GenericClass<T> is actually a different type for each T, so it can have its own static fields (i.e. GenericClass<Foo>.SomeField is not shared with GenericClass<Bar>.SomeField)
For instance you can implement your cache like this:
static class TransformCache<TEntityType>
{
public static EntityTypeTransform<TEntityType> Transform { get; set; }
}
And use it like this:
TransformCache<TaskParameter>.Transform = new TaskParameterEntityTypeTransform();
You can't specify a strong-typed collection that would hold different generic types. Here's the approach I've used in a similar problem, modified to match your requirement:
class TransformCollection
{
private Hashtable cache = new Hashtable();
public void Add<T>(EntityTypeTransform<T> transform) where T : class
{
this.cache[typeof(T)] = itemToCache;
}
public bool Exists<T>() where T : class
{
return this.cache.ContainsKey(typeof(T));
}
public EntityTypeTransform<T> Get<T>() where T : class
{
if (!this.Exists<T>())
throw new ArgumentException("No cached transform of type: " + typeof(T).Name);
return this.cache[typeof(T)] as EntityTypeTransform<T>;
}
}
This gives you type-safe cache for your generic type (though type-safety is enforced by the class's logic, not C#). You can use it as follows:
var collection = new TransformCollection();
collection.Add(SomeMethodToGetTransform<Task>());
//...
if (collection.Exists<Task>())
{
var transform = collection.Get<Task>();
//...
}
You could use an interface that is non-generic and then implement that interface explicitly inside that abstract class, It's pretty common in the .Net library itself:
public interface IEntityTypeTransform
{
Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<TEntityType> : IEntityTypeTransform
where TEntityType : class
{
public virtual Func<IDataRecord, TEntityType> GetDataTransform()
{
return this.GetDataTransformImpl();
}
public abstract Func<IDataRecord, TEntityType> GetDataTransformImpl();
Func<IDataRecord, object> IEntityTypeTransform.GetDataTransform()
{
return this.GetDataTransform();
}
}
You would have to create a non-generic base class, e.g.
public abstract class EntityTypeTransformBase
{
public abstract Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<TEntityType> : EntityTypeTransformBase where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransformImpl();
public override Func<IDataRecord, object> GetDataTransform()
{
return GetDataTransformImpl();
}
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransformImpl()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
Now you can create your dictionary:
var d = new Dictionary<Type, EntityTypeTransformBase>();
d.Add(typeof(TaskParameter), new TaskParameterEntityTypeTransform());
You can use KeyedByTypeCollection to get type-safety and you can define an interface with a covariant type parameter to make sure that only objects of type EntityTypeTransform<T> can be added to the dictionary:
public interface IEntityTypeTransform<out TEntityType> where TEntityType : class
{
TEntityType Transform(IDataRecord dataRecord);
}
public abstract class EntityTypeTransform<TEntityType> : IEntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract TEntityType Transform(IDataRecord dataRecord);
}
public class TaskParameter
{
public int TaskId;
public string Name;
public string Value;
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override TaskParameter Transform(IDataRecord dataRecord)
{
return new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
public class SomeClass
{
public KeyedByTypeCollection<IEntityTypeTransform<object>> TransformDictionary = new KeyedByTypeCollection<IEntityTypeTransform<object>>()
{
new TaskParameterEntityTypeTransform(),
// More transforms here
};
}
Now you can use it like this:
public void SomeMethod(IDataRecord dataRecord)
{
TaskParameter taskParameter = TransformDictionary.Find<TaskParameterEntityTypeTransform>().Transform(dataRecord);
}
I have tried to understand what you exactly want I hope this is exactly what you are looking for!
You shall set in TaskParameter class the correct parameters: TaskId, Name, Value
public abstract class EntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransform();
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransform()
{
return x => new TaskParameter { X = x.FieldCount };
}
}
public class TaskParameter
{
public int X { get; set; }
}
Dictionary<Type, EntityTypeTransform<TaskParameter>> imADict;
Add a non generic interface to your transformers:
public interface IEntityTypeTransform
{
Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<T> : IEntityTypeTransform
{
public abstract Func<IDataRecord, object> GetDataTransform();
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, object> GetDataTransform()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task id"],
};
}
}
Then you can encapsulate your dictionary for ensure that datatypes will always match. Never allow to add a IEntityTypeTransform of a bad type :
public class TransformDistributor
{
private readonly Dictionary<Type, IEntityTypeTransform> _transforms = new Dictionary<Type, IEntityTypeTransform>();
public void Add<T>(EntityTypeTransform<T> type)
{
this._transforms.Add(typeof(T), type);
}
public T Transform<T>(IDataRecord record)
{
var transform = this._transforms[typeof(T)].GetDataTransform()(record);
if (transform is T)
{
return (T)transform;
}
else
{
// theorically can't happen
throw new InvalidOperationException("transformer doesn't return instance of type " + transform.GetType().Name);
}
}
}
The advantage are that at compile time, your are sure that nobody can insert a bad transformer, even if your are not using generics.
Usage :
var transforms = new TransformDistributor();
transforms.Add<TaskParameter>(new TaskParameterEntityTypeTransform());
var taskParameter = transforms.Transform<TaskParameter>(new DataRecord());
I would like to just use RegistrationBuilder to create parts.
example:
public interface IModel
{
String Name { get; }
}
public interface IRepository
{
}
class ModelOne : IModel
{
public String Name { get { return "ModelOne"; } }
}
class ModelTwo : IModel
{
public String Name { get { return "ModelTwo"; } }
}
public interface IRepository<TModel> : IRepository where TModel : IModel
{
}
public class Repository<TModel> : IRepository<TModel> where TModel : IModel
{
}
static void Main(String[] args)
{
var builder = new RegistrationBuilder();
builder.ForTypesDerivedFrom<IModel>()
.Export()
.Export<IModel>();
builder.ForTypesDerivedFrom<IRepository>()
.ExportInterfaces();
var asmCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly(), builder);
var container = new CompositionContainer(asmCatalog);
var one = container.GetExportedValue<IRepository<ModelOne>>();
var two = container.GetExportedValue<IRepository<ModelTwo>>();
}
I can not get the results(the one,the two) I want.
because when i use RegistrationBuilder the all type when wrapped in ProjectingType,but GetExportedValue method did not wrap Generic Parameters in ProjectingType.
My temporary solution is to delete the IsAssignableFrom method in ProjectingType. Now I can get the results(the one,the two) I want.
is there any good solution or correction?
I'm trying to figure out how to register the following decorator scenario with Castle Windsor. I have the following interface:
public interface ICalculate<T> where T : class
{
void Calculate(T value);
}
And a couple of implementations where the last one is a decorator.
public class FooCalculator : ICalculate<Foo>
{
public void Calculate(Foo value)
{
// do something here with the value..
}
}
public class BarCalculator : ICalculate<Bar>
{
public void Calculate(Bar value)
{
// do something else here....
}
}
public class CalculatorDecorator<T> : ICalculate<T> where T : class
{
private readonly ICalculate<T> _calculator;
public CalculatorDecorator(ICalculate<T> calculator)
{
_calculator = calculator;
}
public void Calculate(T value)
{
// do for example some logging...
_calculator.Calculate(value);
}
}
This is my registration code
container.Register(Classes.FromAssembly()
.BasedOn(typeof(ICalculate<>))
.WithService.Base());
When i request one of the implementations by their generic interface I want Windsor to resolve the CalculatorDecorator with the requested implementation injected in the constructor.
// I would like calculator to be CalculatorDecorator<Foo> in
// this case but it is FooCalculator.
var calculator = container.Resolve<ICalculate<Foo>>();
// The same goes for this one...
var calculator = containr.Resolve<ICalculate<Bar>>();
Thanks in advance!
Edit:
It works if I do like this
container.Register(Component.For<ICalculate<Foo>>()
.ImplementedBy<CalculatorDecorator<Foo>>(),
Component.For<ICalculate<Foo>>()
.ImplementedBy<FooCalculator>());
container.Register(Component.For<ICalculate<Bar>>()
.ImplementedBy<CalculatorDecorator<Bar>>(),
Component.For<ICalculate<Bar>>()
.ImplementedBy<BarCalculator>());
But I would prefer to register all components if it's possible.
container.Register(AllTypes.FromAssembly()
.BasedOn(typeof(ICalculate<>))
.WithService.Base());
Did you try this? We had a similar situation and this worked for us.
UPDATE
I don't think this is possible because you'll create a circular dependency.
I did get it working like following:
Registration
var container = new WindsorContainer();
container.Register(Component.For(typeof(IDecorator<>)).ImplementedBy(typeof(CalculatorDecorator<>)));
container.Register(AllTypes.FromThisAssembly()
.BasedOn(typeof (ICalculate<>))
.WithService.Base());
var fc = container.Resolve<IDecorator<Foo>>();
var bc = container.Resolve<IDecorator<Bar>>();
Interfaces:
public interface ICalculate<T> where T : class
{
void Calculate(T value);
}
public interface IDecorator<T> : ICalculate<T> where T : class
{
}
Implementation:
public class FooCalculator : ICalculate<Foo>
{
public void Calculate(Foo value)
{
// do something here with the value..
}
}
public class BarCalculator : ICalculate<Bar>
{
public void Calculate(Bar value)
{
// do something else here....
}
}
public class CalculatorDecorator<T>: IDecorator<T> where T : class
{
private readonly ICalculate<T> _calculator;
public CalculatorDecorator(ICalculate<T> calculator)
{
_calculator = calculator;
}
public void Calculate(T value)
{
// do for example some logging...
_calculator.Calculate(value);
}
}