2008-09-16 3 views
8

Dies sollte hoffentlich ein einfacher sein.Wie Sie eine C# Erweiterungsmethode für eine generisch typisierten Klasse schreiben

Ich möchte eine Verlängerung Methode zum System.Web.Mvc.ViewPage < T> Klasse hinzuzufügen.

Wie soll diese Erweiterung Methode aussehen?

Mein erster intuitiver Gedanke ist so etwas wie diese:

namespace System.Web.Mvc 
{ 
    public static class ViewPageExtensions 
    { 
     public static string GetDefaultPageTitle(this ViewPage<Type> v) 
     { 
      return ""; 
     } 
    } 
} 

Lösung

Die allgemeine Lösung this answer ist.

Die spezifische Lösung zum Erweitern der System.Web.Mvc.ViewPage-Klasse ist my answer unten, die von der general solution gestartet wurde.

Der Unterschied ist im speziellen Fall, dass Sie sowohl eine generisch typisiert Methodendeklaration und eine Erklärung benötigen den generischen Typ als Referenztyp zu erzwingen.

Antwort

16

I VS auf meinem aktuellen Computer nicht installiert haben, aber ich denke, die Syntax wäre:

namespace System.Web.Mvc 
{ 
    public static class ViewPageExtensions 
    { 
     public static string GetDefaultPageTitle<T>(this ViewPage<T> v) 
     { 
      return ""; 
     } 
    } 
} 
+0

Siehe http: // stackoverflow .com/questions/68750/how-do-you-schreiben-ac-extension-method-for-a-generically-typed-class/68802 # 68802 –

3

Es muss nur die generischen Typspezifizierer auf der Funktion:

namespace System.Web.Mvc 
{ 
    public static class ViewPageExtensions 
    { 
     public static string GetDefaultPageTitle<Type>(this ViewPage<Type> v) 
     { 
      return ""; 
     } 
    } 
} 

bearbeiten : Habe es nur um Sekunden verpasst!

5

Dank leddt. Doing, das den Fehler ergab:

The type 'TModel' must be a reference type in order to use it as parameter 'TModel' in the generic type or method

, die mich zu this page hingewiesen, die diese Lösung ergab:

namespace System.Web.Mvc 
{ 
    public static class ViewPageExtensions 
    { 
     public static string GetDefaultPageTitle<T>(this ViewPage<T> v) 
      where T : class 
     { 
      return ""; 
     } 
    } 
} 
1

Wenn Sie die Erweiterung wollen nur für den angegebenen Typ verfügbar sein Sie einfach nur brauchen die tatsächliche Art anzug Sie

so etwas wie ...

Handhabung wird

Hinweis Intellisense wird dann nur die Erweiterungsmethode anzuzeigen, wenn Sie Ihr (in diesem Fall) View mit dem passenden Typ deklarieren.

Auch am besten, um den System.Web.Mvc-Namespace zu verwenden, weiß ich es bequem, um Ihren Namespace nicht in den usings-Abschnitt aufzunehmen, aber es ist viel wartbarer, wenn Sie Ihren eigenen Extensions-Namespace für Ihre Erweiterungsfunktionen erstellen .

1

Glenn Block hat ein gutes Beispiel für die Implementierung einer ForEach Erweiterungsmethode zu IEnumerable<T>.

Von seinem blog post:

public static class IEnumerableUtils 
{ 
    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action) 
    { 
     foreach(T item in collection) 
      action(item); 
    } 
} 
2
namespace System.Web.Mvc 
{ 
    public static class ViewPageExtensions 
    { 
     public static string GetDefaultPageTitle<T>(this ViewPage<T> view) 
      where T : class 
     { 
      return ""; 
     } 
    } 
} 

Sie auch den "new()" Qualifier gattungs (dh müssen/wollen hinzufügen "where T: Klasse, neu()" zu erzwingen, dass T ist sowohl eine Referenz-Typ (Klasse) und einen parameterlosen Konstruktor hat

1

Hier ein Beispiel für Razor Ansichten ist.

public static class WebViewPageExtensions 
{ 
    public static string GetFormActionUrl(this WebViewPage view) 
    { 
     return string.Format("/{0}/{1}/{2}", view.GetController(), view.GetAction(), view.GetId()); 
    } 

    public static string GetController(this WebViewPage view) 
    { 
     return Get(view, "controller"); 
    } 

    public static string GetAction(this WebViewPage view) 
    { 
     return Get(view, "action"); 
    } 

    public static string GetId(this WebViewPage view) 
    { 
     return Get(view, "id"); 
    } 

    private static string Get(WebViewPage view, string key) 
    { 
     return view.ViewContext.Controller.ValueProvider.GetValue(key).RawValue.ToString(); 
    } 
} 

Sie müssen wirklich nicht die generische Version verwenden, da die generische die nicht-generische erweitert, also legen Sie sie einfach in die nicht-generische Basisklasse und Sie sind fertig :)

+0

Neat - Prost für das Posten des Updates. –

Verwandte Themen