【问题标题】:is there any way to pass class object generically to the method有没有办法将类对象一般地传递​​给方法
【发布时间】:2019-11-07 19:22:29
【问题描述】:

我有如下的类对象

public class Version
{

    [JsonIgnore]
    public  string ClassName = "Version";

    [JsonIgnore]
    public string Name { get; set; } = "Version 1";
    .......
    .......
}

我将这个类对象传递给如下方法

class EpJSON
{
    public Dictionary<string, Dictionary<string, object>> model = new Dictionary<string, Dictionary<string, object>>();

    public void Add(dynamic v)
    {
        if (model.ContainsKey(v.ClassName))
        {
            if (model[v.ClassName].ContainsKey(v.Name))
            {
                model[v.ClassName][v.Name] = v;
            }
            else
            {
                model[v.ClassName].Add(v.Name, v);
            }

        }
        else
        {
            Dictionary<string, object> obj = new Dictionary<string, object>() { { v.Name, v } };
            model.Add(v.ClassName, obj);
        }

    }

    public void Save(string path)
    {
        using (StreamWriter file = File.CreateText(path))
        {
            JsonSerializer serializer = new JsonSerializer();
            serializer.Serialize(file, model);
        }
    }

}

我正在调用 Add 方法,如下所示

var model = new EpJSON();
var ver1 = new Version() { VersionIdentifier = "9.2" };
model.Add(ver1);
var ver2 = new Version() { Name = "V2", VersionIdentifier = "9.3" };
model.Add(ver2);
model.Save(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.json"));

我想从你们那里得到建议,是否有任何通用方法可以将 Version 对象传递给方法 Add,并且我可以传递与此对象完全相同的其他对象,并带有额外的字段

如果您需要更多信息,请告诉我

更新代码

public void Add([dynamicObj] v)
{
    if (model.ContainsKey([dynamicObj].ClassName))
    {
        if (model[[dynamicObj].ClassName].ContainsKey([dynamicObj].Name))
        {
            model[[dynamicObj].ClassName][[dynamicObj].Name] = v;
        }
       ......
    }
    ......
}

【问题讨论】:

  • 传递版本对象的通用方式是什么意思?你已经从我能看到的地方传递了它
  • @Steve 我正在寻找是否有任何方法可以动态传递或通用方法来传递版本对象.. 我可能还需要传递一些其他类,而不仅仅是将来的版本
  • 您需要提供一些示例来说明您想要实现的目标。这些类是否共享相同的基类或接口?如果不是,那么您可以通过使用通用方式而不是仅仅接受Add(object o) 来实现什么?如果他们共享一个基类或接口,为什么不直接使用它作为参数呢?
  • @Steve 他们不会共享同一个基类,我更新了问题并添加了一些我正在寻找的代码示例......非常感谢您的支持
  • 什么是dynamicObj.Name?它是动态对象上的一些属性吗?如果是这样,那么您正在寻找第二个参数而不是通用方法。泛型只能传递type,它只包含来自程序集级别的信息,而不是来自运行时的信息。

标签: c# class generics


【解决方案1】:

generic 我不太清楚你的意思。如果要动态调用EpJson 类的Add 方法,可以使用Type 类的GetMethod 函数。这是一个使用 List&lt;string&gt; 的示例,但它肯定适用于任何类型:

var myList = new List<string>();
var addMethod = myList.GetType().GetMethod(nameof(myList.Add));
addMethod.Invoke(myList, new object[] { "hello" });

Console.WriteLine(String.Join(",", myList)); // produces "hello"

编辑:好的,我想我明白你的意思了。你必须使用多态性来实现这一点。假设您要传递具有ClassNameName 属性的对象。然后你可以定义一个像这样的接口:

public interface IObjectWithRequiredProperties
{
    string ClassName { get; set; }
    string Name { get; set; }
}

然后通过将类定义更改为,使您的Version 类成为此接口的实现者

public class Version : IObjectWithRequiredProperties
...

这将强制类包含您在接口上定义的那些属性。现在有趣的部分来了,您必须通过将 Add 方法更改为来使其具有通用性

public void Add<TGeneric>(TGeneric v) where TGeneric: IObjectWithRequiredProperties

现在您可以确定,无论传递给Add 方法,它都将具有IObjectWithRequiredProperties 具有的所有属性。自然,您必须将底层字典更改为您的界面类型。这称为generic type constraint

【讨论】:

  • 您好,我正在寻找将版本对象传递给 add 方法的通用方法。我将来可以传递具有相同属性的其他对象
  • 我需要对字典进行哪些更改以确保它与界面相关
  • 您的字典目前是什么类型的?基本上你需要用 IObjectWithRequiredProperties 或任何你的接口名称替换 Version。
  • 我已经添加了与 Add 方法相关的完整类..你能看到有问题的更新代码吗..你能指导我是否需要对 epjson 类做任何更改
【解决方案2】:

我仍然会建议界面方式,但如果你绝对想做你所描述的,那么dynamic关键字或反射就可以了

    public void Add(dynamic v)
    {
        Type type = v.GetType();

        bool hasClassNameProperty = type.GetProperty("ClassName") != null;
        if (hasClassNameProperty)
        {
            string className = v.ClassName;
        }

        bool hasNameProperty = type.GetProperty("Name") != null;
        if (hasNameProperty)
        {
            string name = v.Name;
        }
    }

    public void Add2(object o)
    {
        Type type = o.GetType();
        PropertyInfo classNameProperty = type.GetProperty("ClassName");
        if (classNameProperty != null)
        {
            string className = (string)classNameProperty.GetValue(o);
        }

        PropertyInfo nameProperty = type.GetProperty("Name");
        if (nameProperty != null)
        {
            string name = (string)nameProperty.GetValue(o);
        }
    }

【讨论】:

  • 非常感谢,但我认为您误解了我的概念,我希望以通用方式仅使用一个变量,而不是将两个参数传递给该方法..希望您理解..我修改了我的更新部分,我只想以通用方式传递单个参数
  • @EnigmaState 您要实现的目标类似于 javascript,其中任何对象都是动态对象并且不是强类型的。您可以使用反射或关键字dynamic 来执行此操作。但我不会推荐它。
  • 我尝试了动态,但它看起来不起作用
  • @EnigmaState 查看更新后的答案。虽然不推荐。这是一种强烈的代码气味。
  • 我无法理解这一行 string className = type.Name; 我确实有 Version 类的属性,例如 ClassNamename 并且两者都有值
猜你喜欢
  • 2021-04-13
  • 2020-04-29
  • 1970-01-01
  • 2012-08-08
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
  • 2019-07-30
  • 1970-01-01
相关资源
最近更新 更多