6

我目前有这种类型的代码:

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 中这样的事情可能吗?如果它比我当前的代码更混乱,那么我认为这样做没有任何意义,但我很想知道。谢谢!

编辑:澄清一下,我完全理解实现接口是最合适且可能正确的解决方案。也就是说,我更感兴趣的是如何在不实现接口的情况下做到这一点。感谢您的精彩回复!

4

7 回答 7

15

看起来您关心的两种类型都实现了相同的两个属性。在这种情况下,您要做的是为这些属性定义一个接口:

public interface IMyInterface
{
   public Foo Property1 {get; set;}
   public Bar Property2 {get;set;}
}

然后,确保您的每个类都告诉编译器它们实现了该新接口。最后,使用带有类型参数的泛型方法,该类型参数受该接口约束:

private void FillObject<T>(T MainObject, Foo Arg1, Bar Arg2) 
    where T : IMyInterface
{
    MainObject.Property1 = Arg1;
    MainObject.Property2 = Arg2;
}

请注意,即使使用额外的代码来声明接口,这些代码段仍然比您在问题中发布的任何一个代码段都要短,并且如果您关心的类型数量增加,则此代码更容易扩展。

于 2009-02-19T18:23:40.823 回答
9

本质上,您在这里所做的是根据对象的类型编写一个 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: //blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx

于 2009-02-19T18:21:16.113 回答
7

您能否对 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;
        }
    }
}
于 2009-02-19T18:22:45.270 回答
4
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);
}
于 2009-02-19T18:22:31.977 回答
3

一些想法:

  1. 让两种类型都继承自具有共同属性的同一类型
  2. 让这两种类型实现具有共同属性的相同接口
  3. 使用反射来设置属性而不是直接设置它们(这可能比它的价值更难看)
  4. 使用新的动态功能,我没有尝试过,但看起来它可能会解决你的问题
于 2009-02-19T18:24:10.917 回答
2

而不是尝试投射,也许您可​​以尝试使用反射设置属性。

于 2009-02-19T18:21:20.857 回答
0

我在 ASP.NET MVC 应用程序中使用反射动态转换对象。基本上我枚举一个类的属性,在数据存储中找到相应的值并动态转换该值并将其分配给对象实例。请参阅我的博客文章 Dynamic Casting with .NET

于 2010-03-31T20:35:41.427 回答