Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从基类实例访问派生类属性_C#_Design Patterns_Reflection - Fatal编程技术网

C# 如何从基类实例访问派生类属性

C# 如何从基类实例访问派生类属性,c#,design-patterns,reflection,C#,Design Patterns,Reflection,我无法访问或更改以下代码: class A{ } class B:A{ string name; int age; string desc; } class C:A{ string name; int age; string desc; } 我需要找到一种方法来编写一个函数,为B和C的实例赋值。最简单的方法是编写两个函数。每班一人 void myFunc(B b){ b.name = "some_name";

我无法访问或更改以下代码:

class A{
}

class B:A{
    string name;
    int age;
    string desc;
}

class C:A{
    string name;
    int age;
    string desc;
}
我需要找到一种方法来编写一个函数,为B和C的实例赋值。最简单的方法是编写两个函数。每班一人

void myFunc(B b){
    b.name = "some_name";
    b.age = 27;
    b.desc = "some_desc";
}

void myFunc(C c){
    c.name = "some_name";
    c.age = 27;
    c.desc = "some_desc";
}
有没有一种方法可以编写一个通用函数来完成这些任务?
当然,这些课程只是例子。在现实世界中,有许多从基类派生的类,每个类都有许多成员。

我们可以找到几种方法来做到这一点。 例如,您可以对类型使用扩展方法:A 并使用反射在其中设置字段

像这样:

public static class ClassExtensions
{
    public static void SetProperties(this A a, string name, int age, string desc)
    {
        Type type = a.GetType();
        type.GetField("name")?.SetValue(a, name);
        type.GetField("age")?.SetValue(a, age);
        type.GetField("desc")?.SetValue(a, desc);
    }
}
以下是它的工作原理:

或者只使用dynamic,例如:

public static void Main(string[] args)
{
    var b = new B();
    SetValues(b, "yes", 5, "ok");

    var c = new C();
    SetValues(c, "no", 10, "not ok");
}

public static void SetValues(dynamic theClass, string name, int age, string desc)
{
    theClass.name = name;
    theClass.age = age;
    theClass.desc = desc;
}

注意:我假设字段或属性是公共的,而不是私有的。

只是好奇:为什么不使用Automapper?它使用基于约定的方法,当这还不够时,您可以自己编写映射代码并将其注入。

这不是一个好的设计。如果你能以任何方式改变它,强烈地考虑这样做,但如果你不能,这是你能做的。< /P> 你不需要对此进行反思。将完成以下工作:

void MyMethod(A a)
{
    if (a is B b)
    {
        b.name = "some_name";
        b.age = 27;
        b.desc = "some_desc";        
    }

    if (a is C c)
    {
        c.name = "some_name";
        c.age = 27;
        c.desc = "some_desc";
    }
}

由于A是一个未密封的基类,其他派生类可能存在于类D:A等中,但由于MyMethod不返回任何内容,因此将任何其他子类型作为参数传递将是不可操作的。

基类对其子类一无所知。如果它们具有相同的名称和类型,为什么它们在派生类而不是基类中?继承的全部理念不是你不复制这样的东西吗?或者,定义接口并在类中实现它们。然后你可以根据类实现的接口设置这些属性。我有下面的代码,我无法访问或更改。你添加了一些有趣的标记,让我来处理它们,你可以使用反射,这是个坏主意,因为简单的更改(如重命名字段)会破坏你的代码,家长应该不知道它的孩子。当您想要编写在不同类型上运行的相同逻辑时,泛型是很好的,例如列表、字典等。因此,在这种情况下,泛型是不必要的。正如其他人所指出的,最好的解决方案是某种基类或使用接口。实际上,您什么也做不了。您甚至不能编写作为示例设置的函数,因为所有属性都是私有的?请注意,D也继承了A,但没有定义任何属性。@MarkSeemann当然,这些解决方案不会使一切都变得完美。我也不是这么建议的。因为我们工作的基础被打破了。但是像b.SetPropertiesyes,5,ok这样的调用看起来是代码中最自然的。但无论如何,我添加了Null条件,这样它就不会崩溃。也就是说,如果你通过了D,它现在就什么也做不了了。@Shay说可能有很多类,所以这种方法可能会产生一个巨大的映射方法。在这一点上,使用某种MappingProvider并在Composition根目录中注册各个映射函数不是更好吗?顺便说一句,马克,伟大的粉丝here@DavidGuida我承认我漏掉了那句话哦,绝对!对我来说,反思永远不会成为一种选择。我建议为每种情况甚至Func创建特定的映射器类,在compositionroot中注册它们,然后通过注册为singleton的映射工厂调用它们。然后,如果您想在映射程序代码中使用反射,请自便:D