2013-01-03 24 views
5

Utworzono silnik, który pobiera wtyczki innych firm (DLL), które implementują interfejs.Czy można utworzyć instancję klasy bez uruchamiania ŻADNEGO kodu z klasy? (brak inicjalizacji, brak inicjalizacji pól)

Ponieważ nie mam kontroli nad kodem, który zostanie podłączony, chcę mieć możliwość uruchomienia 1 określonej metody (z interfejsu) z odpowiedniej klasy (pętla GetTypes, dopóki nie znajdę klasy z interfejsem).

Ponieważ każdy może stworzyć piękny kod konstruktora, który wykonuje na Activator.CreateInstance, że mogę rozwiązać za pomocą FormatterServices.GetUninitializedObject. Ale to nie pomaga, gdy kod jest inicjowany na polach w klasie.

public class myclass : myinterface { 

    public someotherclass name = new someotherclass() 

    public myclass() { 
    //Unknown code 
    } 

    //I only want this run. 
    public string MyProperty{ 
    get { 
     return "ANiceConstString"; 
    } 
    } 
} 

Problem z obu sposobów (CreateInstance/GetUninitializedObject) jest to, że konstruktor zostanie uruchomiony someotherclass.

Zanim zaczniesz analizować moje potrzeby. Jest on uruchamiany tylko podczas inicjowania silnika, aby uzyskać zestaw standardowych wartości. Jeśli ten wynik będzie zależał od innych zainicjowanych wartości, "wtyczka" zostanie oznaczona jako nieudana, ponieważ nie zostanie zwrócona ważna wartość. Jeśli nie zostanie oznaczony jako nieudany, później klasa zostanie poprawnie załadowana przy użyciu Activator.CreateInstance().

Więc trzymaj się tego pytania: Czy .Net obsługuje jakikolwiek sposób utworzenia w 100% niezainicjowanej klasy?

Aktualizacja odpowiedzi. Przetestowałem to, zanim opublikowałem moje pytanie.

Aby uzyskać odpowiedź, której nie można jeszcze uruchomić, testowałem ją i jest ona uruchamiana, jeśli jest statyczna.

public class myclass : myinterface { 

    static Tutle test; 

    public myclass() { 
     test = new Tutle(); 
    } 

    public class Tutle { 
     public Tutle() { 
      MessageBox.Show("RUN!"); 
     } 
    } 
} 

CreateInstance pokazuje wiadomość. GetUninitializedObject nie.

public class myclass : myinterface { 

    static Tutle test = new Tutle(); 

    public myclass() { 
    } 

    public class Tutle { 
     public Tutle() { 
      MessageBox.Show("RUN!"); 
     } 
    } 
} 

CreateInstance pokazuje wiadomość. GetUninitializedObject pokazuje pole wiadomości.

Czy istnieje sposób na poruszanie się w inteli- zatorach pola magnetycznego i lekarzach?

+0

Jeśli naprawdę nie chcesz instancją obiekt ma zostać utworzony, to brzmi jak chcesz * * oferta zamiast statycznego. Tak, to znaczy, że nie możesz określić go w interfejsie ... ale już używasz refleksji, więc możesz po prostu sprawdzić, czy wszystkie typy mają odpowiednią właściwość. Lub jeśli wiesz, że wartość właściwości powinna zawsze być stała, może wymagać zamiast tego niestandardowego atrybutu. –

+2

Kiedy nie masz kontroli nad kodem, który zostanie wykonany, możesz rozważyć wykonanie tego kodu w osobnej domenie AppDomain z ograniczonymi uprawnieniami. Może to być alternatywa dla tworzenia niezainicjowanego obiektu. –

Odpowiedz

14

prostu:

var obj = (myclass)FormatterServices.GetUninitializedObject(typeof(myclass)); 

To nie uruchomić inicjatorów konstruktora/polowych. W ogóle. To nie będzie uruchomić konstruktora dla someotherclass; name będzie null.

Wykona jednak dowolny konstruktor statyczny, który istnieje, jeśli to konieczne, zgodnie ze standardowymi regułami .NET.

JEDNAKŻE! Powinienem zauważyć, że ta metoda nie jest przeznaczona do użytku ad-hoc; jego głównym celem jest użycie w serializerach i silnikach zdalnych. Istnieje bardzo duża szansa, że ​​typy nie będą działały poprawnie, jeśli zostaną utworzone w ten sposób, jeśli nie zostaną podjęte dalsze kroki w celu przywrócenia ich do stanu prawidłowego (co z pewnością zrobiłby każdy silnik serializatora/zdalnego serwera).

+1

Prawidłowo, inicjator pola ('public someotherclass name = new someotherclass();' w twoim przykładzie) * nie * zostanie wykonany. –

+0

Sprawdź moją aktualizację. GetUninitializedObject uruchamia kod ... Allready przetestowano przed wysłaniem. NM. Problemem był statyczny. A więc nie ma sposobu na poruszanie się statycznie? – Wolf5

+1

@ Wolf5 Testowałem też: p i nie: nie jest (edytuj: ten komentarz jest już nieaktualny, ponieważ jest teraz oznaczony jako 'static') Zaktualizowano –

5

Jako alternatywny uwagę design:

[SomeFeature("ANiceConstString")] 
public class myclass : myinterface { 

    public someotherclass name = new someotherclass() 

    public myclass() { 
    //Unknown code 
    } 
} 

Teraz można uzyskać dostęp do funkcji bez instancji; wystarczy użyć:

var attrib = (SomeFeatureAttribute)Attribute.GetCustomAttribute(
    type, typeof(SomeFeatureAttribute)); 
string whatever = attrib == null ? null : attrib.Name; 

z:

[AttributeUsage(
    AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)] 
public sealed class SomeFeatureAttribute : Attribute 
{ 
    private readonly string name; 
    public string Name { get { return name; } } 
    public SomeFeatureAttribute(string name) { this.name = name; } 
} 
+0

Dzięki. Myślę, że dodam to. Ponieważ interfejs jest publikowany i ustawiany, mogę dokonać wstępnego sprawdzenia, jeśli atrybut jest ustawiony, i użyć go przed utworzeniem instancji. Kompatybilność wsteczna. – Wolf5

+0

Podoba mi się to o wiele lepiej. 'GetUninitializedObject' brzmi bardzo niebezpiecznie! –

Powiązane problemy