题
我目前有这种类型的代码:
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
if (MainObject is SomeClassType1)
{
SomeClassType1 HelpObject = (SomeClassType1)MainObject;
HelpObject.Property1 = Arg1;
HelpObject.Property2 = Arg2;
}
else if (MainObject is SomeClassType2)
{
SomeClassType2 HelpObject = (SomeClassType2)MainObject;
HelpObject.Property1 = Arg1;
HelpObject.Property2 = Arg2;
}
}
假设 SomeClassType1 和 SomeClassType2 具有我想要分配的相同属性集(尽管它们在其他属性中可能有所不同),是否可以动态地将 MainObject 转换为适当的类型,然后分配值,而不重复代码?这就是我最终希望看到的:
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
Type DynamicType = null;
if (MainObject is SomeClassType1)
{
DynamicType = typeof(SomeClassType1);
}
else if (MainObject is SomeClassType2)
{
DynamicType = typeof(SomeClassType2);
}
DynamicType HelpObject = (DynamicType)MainObject;
HelpObject.Property1 = Arg1;
HelpObject.Property2 = Arg2;
}
显然 C# 抱怨无法找到 DynamicType:
找不到类型或命名空间名称“DynamicType”(是否缺少 using 指令或程序集引用?)
C# 2.0 中可能有这样的事情吗?如果它比我当前的代码更混乱,那么我认为这样做没有意义,但我很有兴趣找出答案。谢谢!
编辑:只是为了澄清,我完全理解实现接口是最合适且可能正确的解决方案。也就是说,我更感兴趣的是如何在不实现接口的情况下做到这一点。感谢您的精彩回复!
解决方案
它看起来像两个你关心实现相同的两个属性的类型。在这种情况下,你想要做的就是定义一个接口这些属性:
public interface IMyInterface
{
public Foo Property1 {get; set;}
public Bar Property2 {get;set;}
}
然后,确保每个类的告诉他们实现新的界面编译器。最后,使用一个通用的方法,该被约束到该interace类型参数:
private void FillObject<T>(T MainObject, Foo Arg1, Bar Arg2)
where T : IMyInterface
{
MainObject.Property1 = Arg1;
MainObject.Property2 = Arg2;
}
请注意,即使额外的代码申报的接口,这些片段最终仍小于要么你在问题中张贴的片断之一,该代码是容易得多,如果类型的数量,你关心的增加,延长
其他提示
从本质上讲,你在这里做什么基础上的类型FO对象写一个switch语句。有比你的第一个例子要做到这一点其他的(这充其量是乏味)没有固有的好办法。
我写了一个小框架上的类型,使语法更简洁一点的切换。它允许你写的代码如下所示。
TypeSwitch.Do(
sender,
TypeSwitch.Case<Button>(
() => textBox1.Text = "Hit a Button"),
TypeSwitch.Case<CheckBox>(
x => textBox1.Text = "Checkbox is " + x.Checked),
TypeSwitch.Default(
() => textBox1.Text = "Not sure what is hovered over"));
博客帖子: HTTP://博客.msdn.com / jaredpar /存档/ 2008/05/16 /接通-types.aspx
您可以更改SomeClassType1,SomeClassType2等?如果是的话,我会建议你创建一个包含您共同属性,然后强制转换为FillObject()
在这个界面来设置属性的界面。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SO566510
{
interface IMyProperties
{
int Property1 { get; set; }
int Property2 { get; set; }
}
class SomeClassType1 : IMyProperties
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
class SomeClassType2 : IMyProperties
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var obj1 = new SomeClassType1();
var obj2 = new SomeClassType2();
FillObject(obj1, 10, 20);
FillObject(obj2, 30, 40);
}
private static void FillObject(IMyProperties objWithMyProperties
, int arg1, int arg2)
{
objWithMyProperties.Property1 = arg1;
objWithMyProperties.Property2 = arg2;
}
}
}
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
Type t = MainObject.GetType();
t.GetProperty("Property1").SetValue(MainObject, Arg1, null);
t.GetProperty("Property2").SetValue(MainObject, Arg2, null);
}
一些想法:
- 让两种类型都继承自具有共同属性的同一类型
- 让两种类型实现具有共同属性的相同接口
- 使用反射来设置属性而不是直接设置它们(这可能比它的价值更难看)
- 使用新的 动态的 特征, ,我还没有尝试过这个,但看起来它可能会解决你的问题
而不是试图投,也许你可以尝试使用反射设置属性。
我动态铸造在ASP.NET MVC应用程序使用反射物体。基本上我枚举类的属性,找到在数据存储器中的对应值,并动态投射的值,并将其分配给对象实例。请参见我的博客文章 动态使用.NET
铸造