使用实现接口的类

时间:2016-06-22 19:42:54

标签: c# interface

上下文:

我想拥有两个库 - 一个是使用现有实现的遗留库,另一个是带有验证等的一些流程的更精简版本。此外,从长远来看,删除多余的数据。

我在非遗留库中有两个接口:

public interface IMyAttribute
{
  int Id { get; set; }
  dynamic Value { get; set; } // if Value can be of different types, is there a better way?

  bool IsValid();
} 

public IMyData
{
  List<IMyAttribute> data { get; set; };

  void SetProperties();
  bool IsValid();
}

我将遗留库设置为引用&#34; new&#34;图书馆。对于IMyAttribute的遗留实现,IsValid返回true,因为目前没有现有的验证。这将从一个表中提取数据,该表将设置其AttributeValue,AttributeValueNumber或AttributeValueDate字段,并且应该相应地表现(string,double,DateTime),因此使用动态Value。对于IMyData的遗留实现,我已经向对象添加了属性,而SetProperties设置了该实例的属性。

我的问题是,我基本上与它看起来的界面有关。或者更确切地说,我尝试这样做的方式我似乎只能链接到界面。我的目标是&#34;我将拥有带有这些参数的方法,这些或多或少的回报。&#34;但是我试图这样做并遇到问题:

public class MyLegacyAttribute : IMyAttribute
{
  //implementing items from interface plus other methods and properties
}

public class MyLegacyData : IMyData
{
  ...
  List<MyLegacyAttribute> data { get; set; }
  ...
}

有没有一种方法可以这样做,保持合同性质,还是我处理错误?我尝试将IMyData修改为:

List<T> data where T : IMyAttribute { get; set; }
List<T> data { get; set; } where T : IMyAttribute // didn't think this would work, but gave it a shot.

无济于事。

1 个答案:

答案 0 :(得分:1)

根本不清楚你的具体问题是什么。如果你提供一个很好的Minimal, Complete, and Verifiable code example来清楚显示你正在尝试做什么,以及精确描述该代码现在正在做什么,那将会有所帮助,以及它与你想要它做的有什么不同。非常具体。

与此同时,我可以提供一些可能会有所帮助的想法。

首先,不要在界面中使用dynamic。没有意义。如果您不能使界面通用,那么只需使用object。如果确实需要该功能,则使用该接口的代码可以将object分配给dynamic。更有可能的是,它也应该不使用dynamic,而应该转换为已知类型并以这种方式访问​​成员。

但最好是,您可以使界面通用。即:

public interface IMyAttribute<T>
{
  int Id { get; set; }
  T Value { get; set; }

  bool IsValid();
}

当然,这样做会导致使用该接口的所有代码也必须是类型感知的。但从长远来看,这将是非常好的,因为您将避免出现问题,并且会进行编译时类型检查。

关于MyLegacyData类型的问题,虽然您对此并不十分清楚,但似乎您遇到的问题是List<MyLegacyAttribute> 不是List<IMyAttribute>相同或甚至兼容,即使MyLegacyAttribute实现IMyAttribute。原因应该是明确的:MyLegacyData对象可以被任何其他代码视为IMyData,然后该代码可以始终访问data元素(应该恕我拼写{{ 1}})作为Data。然后,该代码可以尝试将List<IMyAttribute>的一些实现添加到除实际类型IMyAttribute所需的MyLegacyAttribute之外的列表中。

编译器不会让你这么做,原因很充分。

如果您可以使MyLegacyData成为通用界面,那么您也可以一般定义IMyData。例如:

MyLegacyData

你可以将这两个想法结合起来:

public IMyData<T> where T : IMyAttribute
{
  List<T> data { get; set; };

  void SetProperties();
  bool IsValid();
}

public class MyLegacyData<T> : IMyData<T> where T : IMyAttribute
{
  ...
  List<T> data { get; set; }
  ...
}

如果您出于某种原因需要非通用版本,那么您仍然可以创建一个子类:

public interface IMyAttribute<T>
{
  int Id { get; set; }
  T Value { get; set; }

  bool IsValid();
}

public IMyData<TData, TValue> where TData : IMyAttribute<TValue>
{
  List<TData> data { get; set; };

  void SetProperties();
  bool IsValid();
}

public class MyLegacyData<TData, TValue> : IMyData<TData, TValue>
    where TData : IMyAttribute<TValue>
{
  ...
  List<TData> data { get; set; }
  ...
}

或者,如果它只是必须一直输入全名,您可以为该类型添加别名:

public class MyNongenericLegacyData : MyLegacyData<MyLegacyAttribute>
{ }

以上内容可以完全解决您的问题。如果是这样,很好。如果没有,请改进问题,以便更清楚您的问题。