简体   繁体   English

C#类,接口和约束

[英]C# Classes, Interfaces and Constraints

I have a project where I need to achieve the following : 我有一个项目需要实现以下目标:

Say I have an interface called "ITemplate" and I define a number of classes "templates" based on that interface. 假设我有一个名为“ ITemplate”的接口,并基于该接口定义了许多类“模板”。

  • TemplateA TemplateA
  • TemplateB TemplateB
  • .... ....
  • TemplateZ TemplateZ

If I want create a LIST of any templates I can use 如果我想创建任何模板的列表,可以使用

List<ITemplate> myList = new List<ITemplate>();
myList.Add(TemplateA);
myList.Add(TemplateC);
myList.Add(TemplateX);

etc - that's fine. 等-很好。

Say now I want to create a number of special lists so that 现在说我要创建一些特殊列表,以便

myListAlphaTemplates can only have a defined subset of all templates, and myListBetaTemplates can only have a different defined subset of all templates myListAlphaTemplates只能具有所有模板的已定义子集,而myListBetaTemplates只能具有所有模板的不同已定义子集

What is the best way to achieve this? 实现此目标的最佳方法是什么?

So the code i have at the moment is along the lines of the following ( the real code is too large to post) 所以我目前的代码如下(实际代码太大而无法发布)

Define the template interface 定义模板界面

interface ITemplateConstraint 
{ }

Define more interfaces for each list type 为每种列表类型定义更多接口

interface SpecialListOne : ITemplateConstraint
{ }

interface SpecialListTwo : ITemplateConstraint
{ }

Now I define an actual "template" 现在,我定义一个实际的“模板”

public class TemplateA : SpecialListOne , SpecialListTwo 
{     ....    }

public class TemplateB : SpecialListOne 
{     ....    }

public class TemplateC : SpecialListTwo 
{     ....    }

And finally I add my lists 最后,我添加我的列表

List<SpecialListOne> ListofTypeOne;   // this can be TemplateA  or TemplateB 
List<SpecialListTwo> ListofTypeTwo;   // this can be TemplateA  or TemplateC 

This works fine, but.. 这很好,但是..

If all of the templates are in a separate library and I have a need to create a new list "SpecialListThree" which only has TemplateC in it, is there a way of doing this without have to amend the actual template definitions themselves? 如果所有模板都在一个单独的库中,并且我需要创建一个仅包含TemplateC的新列表“ SpecialListThree”,是否有办法做到这一点而不必自己修改实际的模板定义?

Its pretty simple, any Enumerable<> has the extension method OfType<> . 它非常简单,任何Enumerable<>都有扩展方法OfType<>

An example of its use would be: 其用法的一个示例是:

var myList = new List<ITemplate>();
myList.Add(TemplateA);
myList.Add(TemplateC);
myList.Add(TemplateX);

var myListAlphaTemplates = myList.OfType<AlphaTemplateClass>().ToList();

You can make interfaces for your alpha and beta templates, based on ITemplate, and have your specific classes implement those: 您可以基于ITemplate为alpha和beta模板创建接口,并让您的特定类实现这些接口:

IAlphaTemplate : ITemplate {}

IBetaTemplate : ITemplate {}

TemplateA : IAlphaTemplate {}

TemplateB : IBetaTemplate {}

// etc.

var myListAlphaTemplates = new List<IAlphaTemplate>();
var myListBetaTemplates = new List<IBetaTemplate>();

Well if your want to constrain lists by Type then you can use code such as 好吧,如果您想按Type限制列表,则可以使用如下代码

public class MyList<T> : List<T> where T:ITemplate, new() { }  

var specialList1 = new MyList<TemplateA>();
var specialList2 = new MyList<TemplateB>();

If constraining is on arbitrary condition then you probably need to write your own class wrapping inner list implementation. 如果约束处于任意条件,那么您可能需要编写自己的包装内部列表实现的类。 But constraining will happen at runtime rather than compile time. 但是约束将在运行时而不是编译时发生。 For example: 例如:

public class ConstrainedList<T> : IList<T> where T:ITemplate
{
    private List<T> _inner = new List<T>();
    Func<T, bool> _constraint;

    public ConstrainedList<T>(Func<T, bool> predicate)
    {
       _constraint = predicate;
    }

    #Region IList Implementation

    public void Add(T item)
    {
        if (_constraint(item))
        {
           _inner.Add(item);
        }
        else
        {
           throw new ArgumentException("Does not meet necessary constraint");
        }
    }

    // rest of implementation
    ...

    #End Region
}

var specialList1 = new ConstrainedList<ITemplate>(t => null != t && typeof(TemplateA) == t.GetType());
var specialList2 = new ConstrainedList<ITemplate>(t => null != t && t.SomeMethod() >= 3);

If there is any logic to it, make the special classes inherit from an abstract special class which implements the interface, or make them implement a special interface that inherits from the regular one. 如果有任何逻辑,则使特殊类从实现该接口的抽象特殊类继承,或者使它们实现从常规接口继承的特殊接口。

Otherwise, you cant inforce it. 否则,您将无法强制执行。

您可以定义一个实现该接口的抽象类,然后从该类继承以定义您的具体实现。

interface IQalifiedTemplate
{
     bool IsQaulified(args);
     ITemaplate Template {get;}
}

or 要么

interface IQalifiedTemplate
   : ITemplate
{
     bool IsQaulified(args);
}

you can use IsQualified(...) to determine if it should be added to the list. 您可以使用IsQualified(...)确定是否应将其添加到列表中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM