简体   繁体   中英

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.

  • TemplateA
  • TemplateB
  • ....
  • 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

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?

Its pretty simple, any Enumerable<> has the extension method 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:

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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