我处于第三方控件做某事的情况,这被设置为通用。出于UI原因,我坚持使用此对象。我也有自己的控件,它与我们的数据层接口来做那件事,并在类型 对象 上进行。没有必要的泛型。它弄清楚要做什么,做什么。
这是他们结构的精简版本(注意:我不能改变它。)
public enum ThirdPartyTypesOfActions
{
ThirdPartyDoAction1WithThing,
ThirdPartyDoAction2WithThing,
ThirdPartyDoAction3WithThing
}
public class ThirdPartyActionsToDo
{
public ThirdPartyTypesOfActions TypeOfAction;
}
public class ThirdPartyDoAction1WithThing<T> : ThirdPartyActionsToDo
{
public T Thing;
public Type ThingType;
}
我的:
public enum MyActionTypes
{
Action1,
Action2,
Action3
}
public class MyAction
{
public object Thing;
public MyActionTypes ActionToPerform;
}
所以我有一个转换器,看起来像:
public List<MyAction> ConvertTheirsToMine(List<ThirdPartyActionsToDo> actions)
{
List<MyAction> retval=new List<MyAction>();
foreach (ThirdPartyActionsToDo action in actions)
{
switch (action.TypeOfAction)
{
case ThirdPartyTypesOfActions.ThirdPartyDoAction1WithThing:
retval.Add(HandleAction1(action));
break;
default:
//Yeah, there's more, but they're the same
break;
}
}
return retval;
}
所以有设置。现在我试图实现HandleAction1,这就是问题发生的地方。
这看起来很有希望并编译好:
private MyAction HandleAction1(ThirdPartyActionsToDo action)
{
MyAction retval=new MyAction();
ThirdPartyDoAction1WithThing<object> fullyQualified = (ThirdPartyDoAction1WithThing<object>) action;
retval.ActionToPerform = MyActionTypes.Action1;
retval.Thing = fullyQualified.Thing;
return retval;
}
但是在运行时,它会引发异常,因为它无法强制转换ThirdPartyDoAction1WithThing&lt; string&gt; as ThirdPartyDoAction1WithThing&lt; object&gt;不好。
但是ThirdPartyActionsToDo给了我正在处理的对象的类型。也许我可以用它?
private MyAction HandleAction1(ThirdPartyActionsToDo action)
{
MyAction retval=new MyAction();
Type tt = action.ThingType;
ThirdPartyDoAction1WithThing<tt> fullyQualified = (ThirdPartyDoAction1WithThing<tt>) action;
retval.ActionToPerform = MyActionTypes.Action1;
retval.Thing = (object)fullyQualified.Thing;
return retval;
}
当然,这甚至都不会编译。
低技术“你无法从这里到达”解决方案是在action.ThingType上执行switch语句并单独处理我可能关心的每种类型。显然,我不太关心这个选项,因为我必须为每个动作类型执行此操作。有人看到了摆脱这种泥潭的方法吗?
答案 0 :(得分:1)
由于您的示例似乎只需要转换为Generic类型是为了获取对Thing
属性的引用,您可以使用反射来获取它而不使用强制转换:
public static class PropertyExtractor
{
public static object GetProperty(object model, string propertyName)
{
var modelDescriptorCollection = TypeDescriptor.GetProperties(model);
var modelData = modelDescriptorCollection.Find(propertyName, true);
if (modelData != null)
{
return modelData.GetValue(model);
}
else
{
return null;
}
}
}
使用此类,您可以像这样重写HandleAction1
方法:
private MyAction HandleAction1(ThirdPartyActionsToDo action)
{
MyAction retval=new MyAction();
retval.ActionToPerform = MyActionTypes.Action1;
retval.Thing = PropertyExtractor.GetProperty(action, "Thing");
return retval;
}
答案 1 :(得分:0)
很遗憾这些类型属于第三方库;否则,协变接口或合适的非通用基类可以派上用场。
快速破解(如果你使用的是.NET 4,C#4)将是我们dynamic
:
private MyAction HandleAction1(ThirdPartyActionsToDo action)
{
return new MyAction
{
ActionToPerform = MyActionTypes.Action,
Thing = ((dynamic)action).Thing
};
}
只要ThirdPartyActionsToDo action
参数总是一个ThirdPartyActionsToDo<SomeType>
,这应该可以正常工作。