【问题标题】:C# how can I access the object properties that not exist in the implemented interfaceC#如何访问已实现接口中不存在的对象属性
【发布时间】:2020-05-13 20:46:40
【问题描述】:

请考虑以下代码。我有一个名为 IClass 的接口。

public interface IClass
{
    public string MyProperty { get; set; }
}

我有两个实现这个接口的类:

public class ClassA : IClass
{
    public string MyProperty { get; set; }
}

public class ClassB : IClass
{
    public string MyProperty { get; set; }
    public string MyProperty2 { get; set; }
}

最后我有一个返回 IClass 接口的方法:

public static IClass MethodA()
{
    return new ClassB { MyProperty = "A", MyProperty2 = "B" };
}

我的问题是我无法从 MethodA 访问 MyProperty2

static void Main(string[] args)
{
    Console.WriteLine(JsonSerializer.Serialize(MethodA()));
}

它只返回{"MyProperty":"A"} 我如何才能在不使用多态模型绑定的情况下实际获得 MyProperty2?还有其他方法吗?

【问题讨论】:

  • MethodA() as ClassB?
  • 你到底是什么意思?
  • 需要将方法返回的对象大小写为ClassB。使用(ClassB)MethodA()MethodA() as ClassB
  • 查看我的答案以了解一些替代方案

标签: c# .net asp.net-core interface polymorphism


【解决方案1】:

你需要投射

Console.WriteLine(JsonSerializer.Serialize((ClassB) MethodA()))

但是,这样做首先违背了使用接口的目的。

【讨论】:

  • 感谢您的回答先生,但实际上这是一个简单的例子。在真实场景中,由于泛型方法,我没有机会进行投射。有没有其他方法可以做到这一点。
  • 是的,你需要在运行时使用反射找出底层类,然后循环遍历各种方法并通过反射调用它们。
  • 谢谢,我会去看看:)
【解决方案2】:

可能您必须像这样明确地检查并强制转换它

var data = MethodA();
JsonSerializer.Serialize(data is ClassB ? data as ClassB : data as ClassA ) 

【讨论】:

  • 三元运算符没有最佳类型。这将无法使用 CS0173 进行编译
【解决方案3】:

序列化基于您提供的类型信息。在泛型重载的情况下,这是泛型类型(Serialize<T> 中的T)。您正在调用其中一个泛型重载,而类型推断正在使用 IClass。要解决这个问题,请使用接受Typeoverload

var obj = MethodA();
var json = JsonSerializer.Serialize(obj, obj.GetType(), default);

或显式转换为object,以便将泛型类型推断为object

var json = JsonSerializer.Serialize((object)MethodA(), default);

或者,两者的半结合:

var json = JsonSerializer.Serialize(MethodA(), typeof(object), default);

如果您不希望序列化程序出现这种行为,则必须强制转换为显式类型(假设您知道它和/或可以接受一堆类型检查)

var json = JsonSerializer.Serialize((ClassB) MethodA(), default);

请注意,object 解决方案仅适用于顶级/根对象。如果您的对象图中某处有一个属性声明为IClass,它将不会按照您的意愿进行序列化。不幸的是,您必须使用 object 类型声明这些属性。

另一种方法是为您的接口类型编写custom converter 并自己反映属性。虽然对根对象过度杀伤(鉴于上述解决方案),但它允许您处理接口类型的嵌套对象。一个简单的转换器可以委托给对象的真实类型。

public class IClassConverter : JsonConverter<IClass> 
{
     public override IClass Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options) => throw new NotImplementedException();

     public override void Write(
        Utf8JsonWriter writer,
        IClass obj,
        JsonSerializerOptions options)
     {
         JsonSerializer.Serialize(writer, obj, obj.GetType(), default); // don't pass options, will result in endless loop 
     } 
} 

然后,您可以通过将转换器添加到序列化程序选项来使用它:

var opts = new JsonSerializerOptions();
opts.Converters.Add(new IClassConverter());
IClass obj = MethodA();
var json = JsonSerializer.Serialize(obj, opts);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 2011-04-17
    • 1970-01-01
    • 2013-04-07
    • 2010-12-08
    相关资源
    最近更新 更多