簡體   English   中英

c# - 如何使用接口和/或抽象類正確地執行MULTIPLE“mixins”

[英]c# - How to do MULTIPLE “mixins” correctly with Interfaces and/or Abstract Classes

我希望能夠定義一些對象並將一些“行為”附加到該對象,其中實現不在對象中。 Rails-like:acts_as_taggable。 作為一個具體的例子,我想說任務可以標記。 我不想在任務中編寫任何代碼,除了通過......界面“啟用”行為之外? 這就是我的問題。 您不能將實現放在接口中。 我不想用所有可能的實現污染我的BaseObject [abstract?]類。

對象:任務,注意

行為:Taggable,Emailable,Printable,Deferrable(

任務可以被標記,通過電子郵件發送,打印和推遲。 注釋可以被標記,通過電子郵件發送,打印,但不能延期。

baseobject

public class BaseObject
{
    Guid ID { get; set; }
}

tag.cs

public class Tag : BaseObject
{
    public Guid Id { get; set; }
    public String Title { get; set; }
}

itaggable.cs

public interface ITaggable 
{
    void AddTag(Tag tag);
    ... other Tag methods ... 
}

task.cs

public class Task : BaseObject, ITaggable, IEmailable, IPrintable
{
    Task specified functionality... nothing about "taggging"
}

note.cs

...

TagCollection.cs

public class TagCollection : List<Tag>
{
    public string[] ToStringArray()
    {
        string[] s = new string[this.Count];
        for (int i = 0; i < this.Count; i++)
            s[i] = this[i].TagName;
        return s;
    }

    public override string ToString()
    {
        return String.Join(",", this.ToStringArray());
    }

    public void Add(string tagName)
    {
        this.Add(new Tag(tagName));
    }

ITaggable的實現看起來像

{
    private TagCollection _tc;
    private TagCollection tc
    {
        get
        {
            if (null == _tc)
            {
                _tc = new TagCollection();
            }
            return _tc;
        }
        set { _tc = value; }
    }

    public void AddTag(Tag tag)
    {
        tc.Add(tag);
    }

    public void AddTags(TagCollection tags)
    {
        tc.AddRange(tags);
    }

    public TagCollection GetTags()
    {
        return tc;
    }
}

那么這樣做的正確/最佳方式是什么?

賈森

那么有很多方法取決於你想要實現的方式。 在你的例子中,最好按照以下方式做一些事情:

public interface IBehavior
{
    ... common behavior methods like maybe
    bool Execute(object value)
}

public class Taggable : IBehavior
{
   ... tag specific items
   public bool Execute(object value) { ... }
}

public class Note
{
   public List<IBehavior> Behaviors { get; set; }
   public void ProcessNote()
   {
       this.Behaviors(d=>d.Execute(this));
   }
}

這種變化將允許您始終添加更多行為,而無需對您的類結構進行任何重大更改,例如在您希望支持新行為的每個類上實現接口。 您可能希望在行為類中提出您的常見對象,以便更輕松地使用您的場景。 因此,您可以使用泛型來允許您執行更類型的定義。

你可能也想看看Decorator模式,為你提供更多的想法。

不幸的是,你將不得不在你的類中添加一些代碼,無論是基類還是后代。

但是,您可以將“可標記”類作為私有成員,並將所有方法調用傳遞給該成員對象,但仍需要實現該接口。

像這樣的東西:

interface ITaggable {
    void AddTag(String tag);
}

class TaggableImplementation : ITaggable {
    private Hashset<String> tags = new Hashset<String>();
    public void AddTag(String tag) { tags.Add(tag); }
}

class TaggableClass : ITaggable {
    private ITaggable taggable = new TaggableImplementation();

    public void AddTag(String tag) { taggable.AddTag(tag); }
}

我通過使用部分類在C#中實現了mixins,並將源代碼從模板文件復制到部分類源文件中。 如果您接受一些限制,它可以很好地工作。 我嘗試使用T4預處理器自動生成源文件,但它有點過於繁瑣,所以我編寫了一個非常簡約的工具來復制模板文件中的代碼,這些文件比T4腳本更容易生成。 稍加注意,您甚至可以在編寫模板時使用Intellisense。

對於該工具,請查看:

http://myxin.codeplex.com/

有關示例,請查看Streambolics.Gui的源代碼:

http://streambolicscore.codeplex.com/

要使用Visual Studio內置的T4代碼生成技術創建mixins,您可以查看http://code.logos.com/blog/2009/04/creating_mixins_with_t4_in_visual_studio.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM