2011-10-09 26 views
35

Bir özniteliğin parametresi olarak temsilci kullanmak mümkün mü? Bunun gibiÖznitelik parametresi olarak bir temsilci olması mümkün mü?

:

public delegate IPropertySet ConnectionPropertiesDelegate(); 

public static class TestDelegate 
{ 
    public static IPropertySet GetConnection() 
    { 
     return new PropertySetClass(); 
    } 
} 

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,AllowMultiple=false,Inherited=true)] 
public class WorkspaceAttribute : Attribute 
{ 
    public ConnectionPropertiesDelegate ConnectionDelegate { get; set; } 

    public WorkspaceAttribute(ConnectionPropertiesDelegate connectionDelegate) 
    { 
     ConnectionDelegate = connectionDelegate; 
    } 
} 

[Workspace(TestDelegate.GetConnection)] 
public class Test 
{ 
} 

Ve onun değil mümkünse

, mantıklı alternatifler nelerdir?

cevap

29

Hayır, öznitelik yapıcısı parametresi olarak bir temsilci olamaz. (Bu hacky olduğunu ve hata eğilimli olsa da) bir delegate with reflection oluşturabilir Çözüm olarak Attribute parameter types
: türleri görmek için temsilci tanımını eşleşen soyut yöntemi ile

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)] 
public class WorkspaceAttribute : Attribute 
{ 
    public ConnectionPropertiesDelegate ConnectionDelegate { get; set; } 

    public WorkspaceAttribute(Type delegateType, string delegateName) 
    { 
     ConnectionDelegate = (ConnectionPropertiesDelegate)Delegate.CreateDelegate(delegateType, delegateType.GetMethod(delegateName)); 
    } 
} 

[Workspace(typeof(TestDelegate), "GetConnection")] 
public class Test 
{ 
} 
+2

Aslında bu iyi bir çözümdür. Bunu yapmak için speficic bir arayüz oluşturdum, ancak delege çok daha kolay. Teşekkürler! –

+0

Bu bir geçici çözüm, ancak iyi değil. Tam olarak @nemesv'in söylediği gibi - hacky ve error prone, çünkü eğer GetConnection yönteminin ismini refactor menüsünü kullanarak değiştirirseniz, "GetConnection" dizesi otomatik olarak değiştirilmeyecektir. – prostynick

+0

Yani C# kurucu argüman türünü manuel olarak kısıtlamak bir olasılık var mı? Bu konuda bir şey duymadım, ama 'Attribute' türünde gördüğümüz gibi bu mümkün. Nasıl? – monstr

9

Diğer olası geçici çözüm yaratıyor soyut taban Özellik türünü ve ardından Yöntemin somut özellik sınıfında uygulanması.

Aşağıdaki faydaları vardır:

  • Ek Açıklama daha özlü ve temiz (gibi DSL)
  • yok yansıması
  • Kolay yeniden

Örnek:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple=false, Inherited=true)] 
public abstract class GetConnectionAttribute : Attribute 
{ 
    public abstract IPropertySet GetConnection(); 
} 

public class GetConnectionFromPropertySetAttribute : GetConnectionAttribute 
{ 
    public override IPropertySet GetConnection() 
    { 
     return new PropertySetClass(); 
    } 
} 

[GetConnectionFromPropertySet] 
public class Test 
{ 
} 
1

Bunu kullanarak çözdüm bir enum ve bir delege listesi eşleme. Gerçekten de miras kullanma fikrini beğenmeme rağmen, senaryomda, birkaç çocuk dersi yazmam için bana nispeten basit şeyler yapmam gerekecek. Bu da refactorable olmalıdır. Tek dezavantajı, dizideki temsilci dizininin enum değerine karşılık geldiğinden emin olmanız gerektiğidir.

public delegate string FormatterFunc(string val); 

public enum Formatter 
{ 
    None, 
    PhoneNumberFormatter 
} 

public static readonly FormatterFunc[] FormatterMappings = { null, PhoneNumberFormatter }; 

public string SomeFunction(string zzz) 
{ 
    //The property in the attribute is named CustomFormatter 
    return FormatterMappings[(int)YourAttributeHere.CustomFormatter](zzz); 
} 
İlgili konular