Per documentation of LightInject we can create a typed factory and pass a value to it like this:
public class Foo : IFoo
{
public Foo(int value)
{
Value = value;
}
public int Value { get; private set; }
}
public interface IFooFactory
{
IFoo GetFoo(int value);
}
public class FooFactory : IFooFactory
{
private Func<int, IFoo> createFoo;
public FooFactory(Func<int, IFoo> createFoo)
{
this.createFoo = createFoo;
}
public IFoo GetFoo(int value)
{
return createFoo(value);
}
}
And we register it like this:
container.Register<int, IFoo>((factory, value) => new Foo(value));
container.Register<IFooFactory, FooFactory>(new PerContainerLifetime());
And we can call GetFoo like this:
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(42);
So now my question is: we instantiate foo explicitly when we are registering the factory new Foo(value). But what if we want to do it within our GetFoo method based on the value?
public IFoo GetFoo(int value)
{
switch (value)
{
case 1: return new Foo(1);
case 2: return new FooThatImplementsIFoo(2);
case 3: return new AnotherFooThatImplementsIFoo(3);
default: return null;
}
}
I want to be able to call GetFoo and get the proper implementation based on "value".
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(3);
Assert.AreEqual(foo.GetType(),typeof(AnotherFooThatImplementsIFoo));
The key is to remember that within GetFoo method of our factory, we are not invoking the delegate, but only passing around the reference to it. The invocation is when we are registering the factory (by instantiating a Foo object).
So what I did was to create a static Factory class that generates implementations of IFoo based on "value":
container.Register<int, IFoo>((factory, value) => FooFactory.GetInstance);
And my FooFactory looks like this:
public static class FooFactory
{
public static IFoo GetInstance(IServiceFactory serviceFactory, int value)
{
switch (value)
{
case 1:
{
return serviceFactory.GetInstance<Foo>();
}
case 2:
{
return serviceFactory.GetInstance<FooThatImplementsIFoo>();
}
case 3:
{
return serviceFactory.GetInstance<AnotherFooThatImplementsIFoo>();
}
default:
{
return null;
}
}
}
}
So I invoke the delegate by doing this:
var typedFooFactory = container.GetInstance<IFooFactory>();
var foo = typedFooFactory.GetFoo(3);
And now my foo object is of Type AnotherFooThatImplementsIFoo
Assert.AreEqual(foo.GetType(),typeof(AnotherFooThatImplementsIFoo));
Related
I have 2 class which has a different constraint, and I want to create obj for them conditionally in a generic function. Example below.
public class Foo1<T>
where T : class, Interface1, new()
{
// do sth...
}
public class Foo2<T>
where T : class, Interface2, new()
{
//do sth...
}
public static void Create<T>()
{
if(typeof(Interface1).IsAssignableFrom(typeof(T))
{
var obj = new Foo1();
//...
} else if (typeof(Interface2).IsAssignableFrom(typeof(T))
{
var obj = new Foo1();
//...
}
}
And I got the error "There is no implicit reference conversion from T to Interface1/2".
The problem is similar to Similiar to How to conditionally invoke a generic method with constraints?, but I can find a place to add (dynamic).
You can create an instance of a generic class using reflection.
public static void Create<T>()
{
if (typeof(Interface1).IsAssignableFrom(typeof(T)))
{
var d1 = typeof(Foo1<>);
Type[] typeArgs = { typeof(T) };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);
}
else if (typeof(Interface2).IsAssignableFrom(typeof(T))
{
// same for Foo2
}
}
How do I make this expression dynamic based on the generic type passed in the parameter?
In the simplified form:
public static class CompareService
{
public static List<T> Run<T>(List<T> database_list, string directory_path)
{
var csv_list = CompareService.MergeRecordsFromFiles<T>(directory);
return CompareService.RunComparison<T>(database_list, csv_list);
}
public static T CompareData<T>(List<T> database_list, List<T> csv_list)
{
var diff = new List<T>();
foreach (var db_item in database_list)
{
// ...
// if T is of type Deathstar compare reference_number property
// if T is of type Stormtrooper compare id property
// if T is of type Sith compare id and anger_level property
var csv_item = csv_list.FirstOrDefault(x => x.reference_number == db_item.reference_number);
// Comparison code
ComparisonResult result = compareLogic.Compare(db_item, csv_item);
// ...
}
return diff;
}
}
It is called from another generic service:
public static void Whatever<T>(List<T> list)
{
// ...
var directory_path = "C:\";
var delta = CompareService.CompareData<T>(list, directory_path);
// ...
}
The most naive implementation would be to check if your itemToFind can be cast to DeathStar, StormTrooper or Sith and if so call the instances property.
var deathStar = itemToFind as DeathStar;
if(deathStar != null)
return database_list.Where(x => ((DeathStar)x).reference_number == deathStar.reference_number).FirstOrDefault();
else
{
var sith = itemToFind as Sith;
if(sith != null)
return database_list.Where(x => ((Sith)x).anger_level == sith.anger_level).FirstOrDefault();
else
return database_list.Where(x => ((StormTrooper)x).id== ((StormTrooper)item).id).FirstOrDefault();
}
This is quite cumbersome, including many casts. In particular it completely bypasses the actual benefits of generics using any arbitrary type (that fullfills the constraints if existing). In your case you´d have a generic method that will only wortk for three decent types.
A better approach is to let all your classes implement a common interface that defines a property, for instance:
interface IObject {
int Level { get; }
}
Now all classes define that level-property:
clas DeathStar : IObject
{
public int Level { get { return this.reference_number; } }
}
clas Sith : IObject
{
public int Level { get { return this.anger_level; } }
}
clas StormTrooper: IObject
{
public int Level { get { return this.id; } }
}
Than you can use a constraint on your type T to implement that interface:
public static T CompareData<T>(List<T> list, T itemToFind) where T: IObject
Why not like this:
public static T CompareData<T>(List<T> list, Func<T, bool> predicate)
{
return database_list.FirstOrDefault(predicate);
}
And then use it like this:
var itemToFind = new ItemToFind();
var myObjectList = new List<MyObject>();
var item = CompareData<MyObject>(myObjectList, x=> x.MyObjectProperty == itemToFind.Id);
You could add a property selector:
public static class CompareService
{
public static T CompareData<T>(this List<T> list, T itemToFind, Func<T, int> propSelector)
{
int propToFind = propSelector(itemToFind); // cache
return database_list.FirstOrDefault(x => propSelector(x) == propToFind);
}
}
And call it like that:
listOfDeathstars.CompareData(deathStarToFind, ds => ds.reference_number);
listOfStormtroopers.CompareData(trooperToFind, t => t.id);
listOfSiths.CompareData(sithStarToFind, sith => new { sith.id, sith.anger_level});
Note: I added the this keyword in the signature to make it an extension (not sure if you intended that but forgot the keyword). And Where(predicate).FirstOrDefault() can be reduced to FirstOrDefault(predicate).
I've got an interface and a class that implements that interface. That class has a default static instance and can also be constructed explicitly (passing an argument).
How do i configure StrucutreMap so that default instance is the static instance, and if i request an instance with an argument a new one is constructed?
Here's the test that fails
[TestFixture]
public class StructureMapTests
{
[Test]
public void Test_same_interface_default_implemenation_and_with_parameter()
{
IMyInterface defaultImp = new MyImpl(0);
ObjectFactory.Initialize(x =>
{
x.For<IMyInterface>().Use(defaultImp);
x.For<IMyInterface>().Add<MyImpl>().Ctor<int>().IsTheDefault();
});
Assert.AreEqual(defaultImp, ObjectFactory.GetInstance<IMyInterface>());
var instance1 = ObjectFactory.With("value").EqualTo(1).GetInstance<IMyInterface>();
Assert.AreEqual(true, instance1 != defaultImp); //<-- fails here
Assert.AreEqual(1, instance1.GetValue());
var instance2 = ObjectFactory.With("value").EqualTo(2).GetInstance<IMyInterface>();
Assert.AreEqual(true, instance1 != defaultImp);
Assert.AreEqual(2, instance2.GetValue());
}
public interface IMyInterface
{
int GetValue();
}
public class MyImpl : IMyInterface
{
private int _value;
public MyImpl(int value)
{
_value = value;
}
public int GetValue()
{
return _value;
}
}
}
I think that the problem that you are facing is that when registering multiple implementations for the same interface, the last one is the one that is going to be resolved by GetInstance. To solve this, you could name your configurations.
Try the following:
[TestFixture]
public class StructureMapTests
{
[Test]
public void Test_same_interface_default_implemenation_and_with_parameter()
{
IMyInterface defaultImp = new MyImpl(0);
ObjectFactory.Initialize(x =>
{
x.For<IMyInterface>().Add<MyInterface>().Named("withArgument").Ctor<int>().IsTheDefault();
x.For<IMyInterface>().Use(defaultImp).Named("default");
});
Assert.AreEqual(defaultImp, ObjectFactory.GetInstance<IMyInterface>());
var instance1 = ObjectFactory.With("value").EqualTo(1).GetInstance<IMyInterface>("withArgument");
Assert.AreEqual(true, instance1 is MyInterface);
Assert.AreEqual(1, instance1.GetValue());
var instance2 = ObjectFactory.With("value").EqualTo(2).GetInstance<IMyInterface>("withArgument");
Assert.AreEqual(true, instance2 is MyInterface);
Assert.AreEqual(2, instance2.GetValue());
}
public interface IMyInterface
{
int GetValue();
}
private class MyInterface : IMyInterface
{
private int _value;
public MyInterface(int value)
{
_value = value;
}
public int GetValue()
{
return _value;
}
}
}
Lets say I have a generic class:
class Foo {
// protected Type t;
// public void SetT(string strval) {
// ((Foo<t>)this).Set(strval);
// }
}
class Foo<T> : Foo {
private T val;
public void Set(string strval) {
if (this is Foo<float>) {
this.val = float.Parse(strval);
} else if (this is Foo<int>) {
this.val = int.Parse(strval);
}
}
}
Now I create an object and put it in an ArrayList:
ArrayList a = new ArrayList();
a.Append(new Foo<float>);
And then I forget the type of Foo<>. Now, how do I Set? I tried the obvious candidates:
(Foo)a[0].Set("5.0");
(Foo<a[0].GetType()>)a[0].Set("5.0");
but those failed.
Is there a way I can call that Set method without explicitly knowing the type of Foo<>?
If not, can I somehow save type of Foo into Foo.t, and then uncomment and use Foo.SetT?
Ah, generics. Very nice tool if you know how to use them :-)
Regards,
dijxtra
One way is to make your generic Foo class implement an interface:
interface IFoo {
void Set(string strval);
}
class Foo<T> : IFoo {
private T val;
public void Set(string strval) {
...
}
}
Then you can cast to IFoo and call Set():
((IFoo)a[0]).Set("5.0");
There's absolutely no reason to be using generics here. Generics are intended to be used when the type of operations you will be performing are generic. In other words, they are independent of the type(s) on which they are performed. You are doing the opposite: the operation will be different depending on the types.
Given that, you should remove the generic parameter, make Set() and Foo abstract, and derive appropriate classes to handle the different types:
abstract class Foo
{
public abstract void Set(string value);
}
class FooDouble : Foo
{
double val;
public override void Set(string value)
{
this.val = double.Parse(value);
}
}
// Etc.
Then, you should be storing your Foos in a List<T>:
List<Foo> fooList = new List<Foo>();
fooList.Add(new FooDouble());
Later, you can say this:
fooList[0].Set("5.0");
And it will just work! No need to remember!
You want to override the implementation of Set in the derived classes.
class Foo {
public virtual void Set(string val);
}
class Foo<T> : Foo {
public override void Set(string val);
}
In addition to what Jimmy pointed out for your base class, you could use a generic collection instead of an ArrayList and make use of a type converter:
public interface IFoo
{
void Set(string value);
}
public class Foo<T> : IFoo
{
private T val;
public void Set(string value)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if(typeConverter.CanConvertFrom(typeof(string)))
{
val = (T)typeConverter.ConvertFromString(value);
}
else
{
throw new InvalidOperationException();
}
}
}
The above will work with either your ArrayList:
ArrayList a = new ArrayList();
a.Append(new Foo<float>());
((IFoo)a[0]).Set("123.4");
Or with a typed collection:
List<IFoo> list = new List<IFoo>();
list.Add(new Foo<float>());
list[0].Set("123.4");
As an added bonus, you don't need to have an if statement in your Set method and try to account for all possible types.
If you want to know the type parameter that was used in you generic, use the GetGenericArguments method.
class Foo<T> {
int input_as_int;
float input_as_float;
public void Set(string strval) {
if (this.GetType().GetGenericArguments().First() == typeof(float)) {
this.input_as_float = float.Parse(strval);
} else if (this.GetType().GetGenericArguments().First() == typeof(int)) {
this.input_as_int = int.Parse(strval);
}
// Else .. throw an exception? return default value? return 0? what makes sense to your application
}
or alternately if you could by pass the Interface entirely and pass the input string in the constructor.
public class Foo<T>
{
public Foo (string input)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if (typeConverter.CanConvertFrom(typeof(string)))
{
Value = (T)typeConverter.ConvertFromString(input);
}
else
{
throw new InvalidOperationException();
}
}
public T Value { get; set;
}
}
then you can just use it like so.
var test = new List<int> Foo ("3");
using System;
using System.Collections;
using System.Collections.Generic;
class Foo {
}
class Foo<T> : Foo {
private T val;
public void Set(string strval) {
var _type = typeof(T);
val = (T)(_type.InvokeMember("Parse", System.Reflection.BindingFlags.InvokeMethod, null, null, new Object[] { strval }));
}
override public string ToString(){
return String.Format("{0}", val);
}
}
class Sample {
static void Main(string[] args){
ArrayList a = new ArrayList();
a.Add(new Foo<float>());
a.Add(new Foo<int>());
dynamic ax = a[0];
ax.Set("5.5");
ax = a[1];
ax.Set("55");
//EDIT
//But I may have to set the float value to Foo <int> If you forgot
// ((Foo<float>)a[0]).Set("5.5");
// ((Foo<int>)a[1]).Set("55");
Console.WriteLine("{0},{1}", a[0], a[1]);
}
}
I have class Foo<T> and an instance method Foo<T>.M with return type T and signature M(Bar bar). There is a constraint on T (T : AbstractBaseClass) so that I'm certain that T has a property T.SomeProperty (and a parameterless constructor constraint). Let's say that M has to set the value of T.SomeProperty based on bar as well on the concrete type of T. I do not want my code to look like
T t = new T();
if(typeof(T) == T1) {
T.SomeProperty = // some function of bar
}
else if(typeof(T) == T2) {
T.SomeProperty = // some function of bar
}
else if(typeof(T) == T3) {
T.SomeProperty == // some function of bar
}
I do not want to put an instance method on T that takes in values from Bar to populate T.SomeProperty because that will make my Ts have a dependency on some things that I do not want it to them a dependency on.
What is my best option here?
Here's what I mean:
class AbstractBaseClass {
public int SomeProperty { get; set; }
}
class Foo<T> where T : AbstractBaseClass, new() {
public T M(Bar bar) {
T t = new T();
t.SomeProperty = // function of bar, typeof(T)
return t;
}
}
How to write M but avoid type-by-type logic on the type parameter T?
Edit:
What about this? This is riffing on Corey's idea:
interface ISomePropertyStrategy<T> {
int GetSomeProperty(Bar bar);
}
class SomePropertyStrategyForConcreteClass1 :
ISomePropertyStrategy<ConcreteClass1> {
public int GetSomeProperty(Bar bar) { return bar.MagicValue + 73; }
}
class SomePropertyStrategyForConcreteClass2 :
ISomePropertyStrategy<ConcreteClass2> {
public int GetSomeProperty(Bar bar) { return bar.MagicValue - 12; }
}
class Foo<T> where T : AbstractBaseClass, new() {
private readonly ISomePropertyStrategy<T> strategy;
public Foo<T>(ISomePropertyStrategy<T> strategy) {
this.stragety = strategy;
}
public T M(Bar bar) {
T t = new T();
t.SomeProperty = this.strategy.GetSomeProperty(bar);
return t;
}
}
The only thing I don't like about this is that it uses a generic interface where the generic type parameter never appears in the interface. I think I once saw a comment from Eric Lippert where he said that wasn't a good idea, but I can't remember. Sorry.
So you have this:
class Foo<T>
where T : AbstractBaseClass, new()
{
T M( Bar bar )
{
T t = new T();
if ( typeof (T) == T1 )
{
t.SomeProperty = bar.SomeMethod();
}
else if ( typeof (T) == T2 )
{
t.SomeProperty = bar.SomeOtherMethod();
}
else if ( typeof (T) == T3 )
{
t.SomeProperty == bar.YetAnotherMethod();
}
}
}
You could do this:
T M( Bar bar, Func<object> barFunction )
{
T t = new T();
t.SomeProperty = barFunction();
}
It doesn't require tight coupling with your Bar method. Here is some information on the Func<T> delegate.
OK, here's a complete program. For the sake of the example, I take Bar to be some class that holds an interesting value (here, 100). I take foo.M to be a routine that wants to add 73 to the number inside Bar if the type argument is ConcreteClass1; it will want to subtract 12 from the number inside Bar if the type argument is ConcreteClass2.
The interface IABCVisitor and the virtual methods AcceptVisitor (one per class) may seem like a lot of overhead, but the nice thing is that you only have to pay that overhead once: once this pattern has been added to your class hiearchy you can reuse it over and over again, whenever your callers want to do custom logic based on type. I hope the program below makes sense to you.
using System;
using System.Diagnostics;
namespace ConsoleApplication33 {
public class Program {
public static void Main() {
var foo1=new Foo<ConcreteClass1>();
var foo2=new Foo<ConcreteClass2>();
var bar=new Bar(100);
var result1=foo1.M(bar);
var result2=foo2.M(bar);
Debug.Print("result1.SomeProperty="+result1.SomeProperty);
Debug.Print("result2.SomeProperty="+result2.SomeProperty);
}
}
//----------------------------------------------------------------------------
// these definitions can appear in project 1
// notice that project 1 does not have any dependencies on Bar
//----------------------------------------------------------------------------
/// <summary>
/// This interface needs a line for each class in the hierarchy
/// </summary>
public interface IABCVisitor<out T> {
T Visit(AbstractBaseClass x);
T Visit(ConcreteClass1 x);
T Visit(ConcreteClass2 x);
}
public abstract class AbstractBaseClass {
public int SomeProperty { get; set; }
/// <summary>
/// All of AbstractBaseClasses' children need to override this property
/// </summary>
public virtual T AcceptVisitor<T>(IABCVisitor<T> visitor) {
return visitor.Visit(this);
}
}
public class ConcreteClass1 : AbstractBaseClass {
public override T AcceptVisitor<T>(IABCVisitor<T> visitor) {
return visitor.Visit(this);
}
}
public class ConcreteClass2 : AbstractBaseClass {
public override T AcceptVisitor<T>(IABCVisitor<T> visitor) {
return visitor.Visit(this);
}
}
//----------------------------------------------------------------------------
// these definitions can appear in project 2
//----------------------------------------------------------------------------
public class Bar {
public int MagicValue { get; private set; }
public Bar(int magicValue) {
MagicValue=magicValue;
}
}
public class Foo<T> where T : AbstractBaseClass, new() {
public T M(Bar bar) {
T t=new T();
t.SomeProperty=t.AcceptVisitor(new CalculateTheRightValue(bar));
return t;
}
}
public class CalculateTheRightValue : IABCVisitor<int> {
private readonly Bar bar;
public CalculateTheRightValue(Bar bar) {
this.bar=bar;
}
public int Visit(AbstractBaseClass x) {
throw new NotImplementedException("not implemented for type "+x.GetType().Name);
}
public int Visit(ConcreteClass1 x) {
return bar.MagicValue+73;
}
public int Visit(ConcreteClass2 x) {
return bar.MagicValue-12;
}
This looks like a pretty classic application of the Visitor Pattern