2008-12-18 6 views
5

Ich habe eine separate Assembly erstellt, die allgemeine Erweiterungsmethoden enthält. Die Erweiterungsmethoden verwenden Klassen aus System.Web.dll (und anderen).Die Verwendung von eingeschränkten generischen Erweiterungsmethoden in einer separaten Assembly führt zu einem Referenzfehler.

Wenn ich ein neues Projekt (Konsole-Anwendung), dann erstellen, die die Utilities.dll Assembly verweist, die die Erweiterungsmethoden enthalten, ich brauche nicht einen Verweis auf System.Web.dll auf das neue Projekt hinzuzufügen, wenn es nicht die Erweiterungsmethoden nicht verwendet Das reicht jede Klasse in der System.Web.dll Assembly (zum Beispiel System.Web.UI.Control).

Wenn eine der Erweiterungsmethoden eine generische Methode ist, funktioniert alles wie erwartet. Aber sobald ich der generischen Methode eine Beschränkung hinzufüge, die sie auf eine Klasse in der System.Web.dll Assembly beschränkt, wird der Compiler beschweren, dass mein neues Projekt (Konsolenanwendung) einen Verweis auf System.Web.dll benötigt, obwohl das neue Projekt immer noch nichts verwendet diese Versammlung.

Mit anderen Worten, solange ich keine Einschränkung für meine generischen Methoden habe, kompiliert alles, aber sobald ich eine Bedingung hinzufüge, beschwert sich der Compiler.

static void Main(string[] args) 
    { 
     bool isEmpty = "Hello World!".IsNullOrEmpty(); 

     Console.ReadLine(); 
    } 


Update::

Ein Beispiel für meine Erweiterungsmethoden assemble (als Bibliothek Utilities.dll):

public static class StringExtensions 
{ 
    public static bool IsNullOrEmpty(this string value) 
    { 
     return string.IsNullOrEmpty(value); 
    } 
} 

public static class ControlExtensions 
{ 
    // If I remove the where clause it compiles 
    public static T FildChild<T>(this Control parent, string id) 
     where T : Control 
    { 
     throw new NotImplementedException(); 
    } 
} 

And here is a new console application that won't compile (unless I also add a reference to System.Web.dll kompiliert) Wie Marc wies darauf hin, (unten) behebt die fehlerhafte Methode in einem separaten Namespace Puting die Problem.

Aber die Frage bleibt immer noch, warum die Einschränkung ein Problem ist, während der Typ Control wurde bereits als Parameter für die Methode verwendet. und warum ist der Namespace die Lösung, wenn ich bereits oben die Anweisung verwende.

Antwort

5

gut, ja! Um kompilieren zu können, muss es alles in der öffentlichen/geschützten API auflösen können. Andernfalls kann die Einschränkung nicht erzwungen werden. Ich stelle mir vor, dass es die Typen erkennen muss, um zu sehen, ob die Erweiterungsmethode ein Kandidat für eine Methode ist.

Sie könnten versuchen, die Erweiterungsmethoden in einem untergeordneten Namespace zu platzieren, der "Web" enthält - zumindest wird es dann nicht in regulären Code übergehen. Ich habe überprüft, und das behebt das Problem. Es empfiehlt sich, die Namespaces der Erweiterungsmethoden zu trennen, damit der Aufrufer steuern kann, wann sie im Bereich sein sollten.

Um auszuführen, müsste es auch in der Lage sein, alles zu lösen, das intern aber nicht verwendet wird, das in der API herausgestellt wird. Dies ist Standardverhalten.

+0

Ich bin mir nicht sicher, ob ich das vollständig verstehe. 1) Mein Projekt verwendet diesen Typ überhaupt nicht. 2) Die Erweiterungsmethode verwendet bereits diesen Typ im ersten Argument der Methode. Warum löst die Einschränkung diesen Wahnsinn aus? – Yona

+0

Ich glaube nicht, dass dies die Frage beantwortet. Sein Code wird gut kompiliert, selbst wenn Control als Parametertyp referenziert wird, aber nicht, wenn er ihn als Einschränkung * zu derselben Methode * hinzufügt. Er verweist nicht einmal auf die Control-Erweiterungsklasse. –

+0

Überraschenderweise legen Sie die problematische Methode in einem separaten Namespace (mit einem beliebigen Namen, solange es nicht mit den anderen Erweiterungen ist) das Problem behoben. Seltsamerweise. – Yona

1

@Marc gibt Ihnen das Warum. Ich würde vorschlagen, dass Sie als eine gute Übung alles, was sich auf Web-Klassen bezieht, in eine andere Versammlung ausbrechen, sagen Sie Com.Company.Extensions.Web zusätzlich zu Com.Company.Extensions. Dann können Sie sowohl in Web-Projekte als auch nur die Nicht-Web-Erweiterungen in andere Projekte aufnehmen.

+0

Genau so habe ich es gemacht. Ich habe eine .WebUtilities.dll Assembly – Yona

+0

BTW Ich bin mir nicht sicher, ob ich Marc Antwort verstehe bitte überprüfen Sie meinen Kommentar. – Yona