我实际上正在处理的问题与ASP.NET MVC中的映射器有关,但这太复杂了,无法在SO上发布,因此我简化了下面的问题。我将首先发布我的代码,因为它更容易解释我在代码之后想要实现的目标。
支持代码
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;
}
}
我想要做的是动态创建不同的ConcreteClass
并在该创建的对象上调用SomeMethod
,基本上我想将ConcreteClass
传递给BaseClass
,就像你可以Foo
传递BaseFoo
一样。我已经使用以下代码:
class Program
{
static void Main(string[] args)
{
BaseFoo foo = new Foo1();
dynamic bar = ConcreteClassFactory.CreateClass(ConcreteClassFactory.ConcreteClassType.ConcreteClass1);
bar.SomeMethod(foo as dynamic);
}
}
然而,这似乎非常难以投射到一个动态(我也不完全理解为什么删除as dynamic
抛出一个RuntimeBinderException
,如果有人可以解释正在发生的事情,那将是值得赞赏的)。有没有更好的方法来实现我在这里要做的事情?
答案 0 :(得分:1)
使用约束,我会做的是从被覆盖的SomeMethod中投射和抛出错误。
public abstract class BaseClass : IMyInterface<BaseFoo>
{
public virtual void SomeMethod(BaseFoo t)
{
t.CommonProperty = 1;
}
}
public class ConcreteClass1 : BaseClass
{
public override void SomeMethod(BaseFoo t)
{
if(t == null)
throw new ArgumentNullException(nameof(t));
var foo1 = t as Foo1;
if(foo1 == null)
throw new NotSupportedException($"{nameof(ConcreteClass1)} does not support types other than {nameof(Foo1)}");
foo1.SomeProperty = 57;
base.SomeMethod(foo1);
}
}
public class ConcreteClass2 : BaseClass
{
public override void SomeMethod(BaseFoo t)
{
if (t == null)
throw new ArgumentNullException(nameof(t));
var foo2 = t as Foo2;
if (foo2 == null)
throw new NotSupportedException($"{nameof(ConcreteClass2)} does not support types other than {nameof(Foo2)}");
foo2.AnotherProperty = 123;
base.SomeMethod(foo2);
}
}
public static class ConcreteClassFactory
{
public enum ConcreteClassType
{
ConcreteClass1,
ConcreteClass2
}
public static BaseClass CreateClass(ConcreteClassType type)
{
BaseClass toReturn = null;
switch (type)
{
case ConcreteClassType.ConcreteClass1:
toReturn = new ConcreteClass1();
break;
case ConcreteClassType.ConcreteClass2:
toReturn = new ConcreteClass2();
break;
default:
break;
}
return toReturn;
}
}
像
一样使用class Program
{
static void Main(string[] args)
{
BaseFoo foo = new Foo1();
var bar = ConcreteClassFactory.CreateClass(ConcreteClassFactory.ConcreteClassType.ConcreteClass1);
bar.SomeMethod(foo);
}
}