The problem I'm actually working on is related to mappers in ASP.NET MVC but that's way too complex to post on SO, so I've simplified the issue I'm having below. I'll post my code first as it's easier to explain what I'm trying to achieve after the code.
Supporting Code
public abstract class BaseFoo
{
public int CommonProperty { get; set; }
}
public class Foo1 : BaseFoo
{
public int SomeProperty { get; set; }
}
public class Foo2 : BaseFoo
{
public int AnotherProperty { get; set; }
}
public interface IMyInterface<T>
{
void SomeMethod(T t);
}
public abstract class BaseClass<T> : IMyInterface<T>
where T : BaseFoo
{
public virtual void SomeMethod(T t)
{
t.CommonProperty = 1;
}
}
public class ConcreteClass1 : BaseClass<Foo1>
{
public override void SomeMethod(Foo1 t)
{
t.SomeProperty = 57;
base.SomeMethod(t);
}
}
public class ConcreteClass2 : BaseClass<Foo2>
{
public override void SomeMethod(Foo2 t)
{
t.AnotherProperty = 123;
base.SomeMethod(t);
}
}
public static class ConcreteClassFactory
{
public enum ConcreteClassType
{
ConcreteClass1,
ConcreteClass2
}
public static dynamic CreateClass(ConcreteClassType type)
{
dynamic toReturn = null;
switch (type)
{
case ConcreteClassType.ConcreteClass1:
toReturn = new ConcreteClass1();
break;
case ConcreteClassType.ConcreteClass2:
toReturn = new ConcreteClass2();
break;
default:
break;
}
return toReturn;
}
}
What I want to do is dynamically create different ConcreteClasss and call SomeMethod on that created object, basically I want to pass around my ConcreteClasss as BaseClass, much like you can pass around Foos as BaseFoo. I've gotten it to work with the following code:
class Program
{
static void Main(string[] args)
{
BaseFoo foo = new Foo1();
dynamic bar = ConcreteClassFactory.CreateClass(ConcreteClassFactory.ConcreteClassType.ConcreteClass1);
bar.SomeMethod(foo as dynamic);
}
}
However, this seems very kludgy to cast to a dynamic (also I don't fully understand why removing as dynamic throws a RuntimeBinderException, if someone can explain what's going on that would be appreciated). Is there a better way to achieve what I'm trying to do here?
ConcreteClass1to useFoo1as it's parameter. @ScottChamberlain ifConcreteClass1were to getFoo2it should throw an error. Obviously I could get rid of the generics and haveSomeMethod(BaseFoo t)but then in each derived class I'd need to try and cast totto the type it expects, not terrible but not ideal for my purposes