c# - Methodenverkettung in C #





(9)


Etwas wie das?

class MyCollection
{
    public MyCollection AddItem(Object item)
    {
        // do stuff
        return this;
    }
}

Ich habe eigentlich keine Ahnung, wie das in C # heißt. Aber ich möchte die Funktionalität zu meiner Klasse hinzufügen, um mehrere Elemente gleichzeitig hinzuzufügen.

myObj.AddItem(mItem).AddItem(mItem2).AddItem(mItem3);



Benutze diesen Trick:

public class MyClass
{
    private List<MyItem> _Items = new List<MyItem> ();

    public MyClass AddItem (MyItem item)
    {
        // Add the object
        if (item != null)
            _Items.Add (item)

        return this;
    }
}

Es gibt die aktuelle Instanz zurück, die es Ihnen ermöglicht, Methodenaufrufe zu verketten (und so mehrere Objekte gleichzeitig hinzuzufügen).




Wenn Ihr Element als Liste fungiert, möchten Sie möglicherweise eine Schnittstelle wie iList oder iEnumerable / iEnumerable implementieren.

Unabhängig davon, der Schlüssel zum Verketten von Anrufen, wie Sie möchten, ist die Rückgabe des gewünschten Objekts.

public Class Foo
{
   public Foo AddItem(Foo object)
   {
        //Add object to your collection internally
        return this;
   }
}



Andere haben in Bezug auf die direkte Methodenverkettung geantwortet, aber wenn Sie C # 3.0 verwenden, könnten Sie an Auflistungsinitialisierer interessiert sein ... sie sind nur verfügbar, wenn Sie einen Konstruktoraufruf ausführen, und nur dann, wenn Ihre Methode über geeignete Add Methoden verfügt Implementiert IEnumerable , aber dann können Sie IEnumerable tun:

MyClass myClass = new MyClass { item1, item2, item3 };



Wie wäre es mit

AddItem(ICollection<Item> items);

oder

AddItem(params Item[] items);

Sie können sie so benutzen

myObj.AddItem(new Item[] { item1, item2, item3 });
myObj.AddItem(item1, item2, item3);

Dies ist keine Methodenverkettung, aber es fügt Ihrem Objekt mehrere Objekte in einem Aufruf hinzu.




"Ich habe eigentlich keine Ahnung, wie das in c # heißt"

Eine flüssige API; StringBuilder ist das häufigste .NET-Beispiel:

var sb = new StringBuilder();
string s = sb.Append("this").Append(' ').Append("is a ").Append("silly way to")
     .AppendLine("append strings").ToString();



Die von Ihnen erwähnte Technik wird als verkettbare Methode bezeichnet. Es wird häufig beim Erstellen von DSLs oder fließenden Schnittstellen in C # verwendet.

Das typische Muster besteht darin, dass Ihre AddItem () - Methode eine Instanz der Klasse (oder der Schnittstelle) zurückgibt, zu der sie gehört. Dadurch können nachfolgende Anrufe an ihn angekettet werden.

public MyCollection AddItem( MyItem item )
{
   // internal logic...

   return this;
}

Einige Alternativen zur Methodenverkettung zum Hinzufügen von Elementen zu einer Sammlung sind:

Verwenden Sie die params , um zu ermöglichen, dass mehrere Elemente als Array an Ihre Methode übergeben werden. Nützlich, wenn Sie die Array-Erstellung ausblenden und eine variable Argumentsyntax für Ihre Methoden bereitstellen möchten:

public void AddItems( params MyItem[] items )
{
    foreach( var item in items )
        m_innerCollection.Add( item );
}

// can be called with any number of arguments...
coll.AddItems( first, second, third );
coll.AddItems( first, second, third, fourth, fifth );

Bereitstellen einer Überladung vom Typ IEnumerable oder IEnumerable, sodass mehrere Elemente gemeinsam an die Sammlungsklasse übergeben werden können.

public void AddItems( IEnumerable<MyClass> items )
{
    foreach( var item in items )
         m_innerCollection.Add( item );
}

Verwenden Sie die Initialisierungssyntax der .NET 3.5-Sammlung. Ihre Klasse muss eine Add( item ) Methode bereitstellen, IEnumerable implementieren und einen Standardkonstruktor haben (oder Sie müssen einen bestimmten Konstruktor in der Initialisierungsanweisung aufrufen). Dann kannst du schreiben:

var myColl = new MyCollection { first, second, third, ... };



Sie können eine Erweiterungsmethode hinzufügen, um dies zu unterstützen, sofern Ihre Klasse von ICollection erbt:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void CanChainStrings()
    {
        ICollection<string> strings = new List<string>();

        strings.AddItem("Another").AddItem("String");

        Assert.AreEqual(2, strings.Count);
    }
}
public static class ChainAdd
{
    public static ICollection<T> AddItem<T>(this ICollection<T> collection, T item)
    {
        collection.Add(item);
        return collection;
    }
}



Wie in @Psyonity erwähnt, können Sie die ConditionalWeakTable verwenden, um vorhandenen Objekten Eigenschaften hinzuzufügen. In Kombination mit dem dynamischen ExpandoObject können Sie dynamische Erweiterungseigenschaften in wenigen Zeilen implementieren:

using System.Dynamic;
using System.Runtime.CompilerServices;

namespace ExtensionProperties
{
    /// <summary>
    /// Dynamically associates properies to a random object instance
    /// </summary>
    /// <example>
    /// var jan = new Person("Jan");
    ///
    /// jan.Age = 24; // regular property of the person object;
    /// jan.DynamicProperties().NumberOfDrinkingBuddies = 27; // not originally scoped to the person object;
    ///
    /// if (jan.Age &lt; jan.DynamicProperties().NumberOfDrinkingBuddies)
    /// Console.WriteLine("Jan drinks too much");
    /// </example>
    /// <remarks>
    /// If you get 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' you should reference Microsoft.CSharp
    /// </remarks>
    public static class ObjectExtensions
    {
        ///<summary>Stores extended data for objects</summary>
        private static ConditionalWeakTable<object, object> extendedData = new ConditionalWeakTable<object, object>();

        /// <summary>
        /// Gets a dynamic collection of properties associated with an object instance,
        /// with a lifetime scoped to the lifetime of the object
        /// </summary>
        /// <param name="obj">The object the properties are associated with</param>
        /// <returns>A dynamic collection of properties associated with an object instance.</returns>
        public static dynamic DynamicProperties(this object obj) => extendedData.GetValue(obj, _ => new ExpandoObject());
    }
}

Ein Verwendungsbeispiel ist in den XML-Kommentaren:

var jan = new Person("Jan");

jan.Age = 24; // regular property of the person object;
jan.DynamicProperties().NumberOfDrinkingBuddies = 27; // not originally scoped to the person object;

if (jan.Age < jan.DynamicProperties().NumberOfDrinkingBuddies)
{
    Console.WriteLine("Jan drinks too much");
}

jan = null; // NumberOfDrinkingBuddies will also be erased during garbage collection



c#  

c#