简体   繁体   English

是否可以“扩展”财产“类”?

[英]Is it possible to “extend” the property “class”?

I'm new to C# (started last week) so be cool with me ;). 我是C#的新手(上周开始),所以对我很冷静;)。 I'd like to know if I can somehow write a custom property, let me explain: 我想知道我是否能以某种方式编写自定义属性,让我解释一下:

I have some partial classes that I complete by adding properties, but the pattern of all the getters and setters are the same so I'd like to factorize this: 我有一些部分类,我通过添加属性完成,但所有getter和setter的模式是相同的,所以我想分解这个:

public partial class Travel
{
    public String TravelName
    {
        get
        {
            return LocaleHelper.GetRessource(Ressource1);
        }
        set
        {
            if (this.Ressource1 == null)
                Ressource1 = new Ressource() { DefaultValue = value };
            else
                Ressource1.DefaultValue = value;
        }
    }

    public String TravelDescription
    {
        get
        {
            return LocaleHelper.GetRessource(Ressource2);
        }
        set
        {
            if (this.Ressource2 == null)
                Ressource2 = new Ressource() { DefaultValue = value };
            else
                Ressource2.DefaultValue = value;
        }
    }
}

As you can see, the only thing that change is Ressource1/Ressource2. 正如您所看到的,唯一改变的是Ressource1 / Ressource2。 My goal is be able to write something like: 我的目标是能够写出如下内容:

public partial class Travel
{
    public LocalizedString TravelName(Ressource1);

    public LocalizedString TravelDescription(Ressource2);
}

Anybody have an idea to make this, or another idea to make my code cleaner? 有人有想法让这个或其他想法让我的代码更干净吗? Thank you, 谢谢,

Guillaume 纪尧姆

There is no facility to do this inside C# or .NET itself, but if you are doing lots of these it may be worth investigating aspect orientated programming through postsharp . 在C#或.NET本身内没有设施可以做到这一点,但是如果你正在做很多这样的事情,那么通过postharp调查面向方面的编程可能是值得的。 Basically it will allow you to define an attribute that causes extra code to be injected at compile time. 基本上它允许您定义一个属性,该属性导致在编译时注入额外的代码。 The code you type be something like: 您输入的代码如下:

public partial class Travel
{
    [LocalizedProperty(source = "Ressource1")
    public string TravelName { get; set; }

    [LocalizedProperty(source = "Ressource2")
    public string TravelDescription{ get; set; }
}

And at compile time PostSharp will replace the property with a template you have defined in the new LocalizedPropertyAttribute class. 在编译时,PostSharp将使用您在新LocalizedPropertyAttribute类中定义的模板替换该属性。

You can't make it quite as succinct as what you describe, but you can decrease the complexity and redundancy of the setters. 你不能让它简明扼要你的描述,但可以降低的setter方法的复杂性和冗余。

private void SetRessource(ref Ressource res, string value)
{
    if(res == null) res = new Ressource();

    res.DefaultValue = value;
}

public String TravelName
{
    get { return LocaleHelper.GetRessource(Ressource1); }
    set { SetRessource(ref this.Ressource1, value); }
}

public String TravelDescription
{
    get { return LocaleHelper.GetRessource(Ressource2); }
    set { SetRessource(ref this.Ressource2, value); }
}

I don't know exactly what you are trying to achieve, but you may be making things too complicated. 我不确切地知道你想要实现什么,但你可能会让事情变得太复杂。 Wouldn't this be sufficient? 这不够吗?

public class Travel
{
   /// <summary>
   /// Creates a new instance of <see cref="Travel"/>.
   /// </summary>
   public Travel()
   {
      this.TravelName = Resources.DefaultTravelName;
      this.TravelDescription = Resources.DefaultTravelDescription;
   }

   public string TravelName { get; set; }

   public string TravelDescription { get; set; }
}

where Resources is a generated class (from a resx file) for localized resources. 其中Resources是本地化资源的生成类(来自resx文件)。 I have a feeling you are trying to build your own localization framework because you don't know yet that .NET already has infrastructure for that . 我有一种感觉,你正在尝试构建自己的本地化框架,因为你还不知道.NET 已经有了基础设施

No, there is no such way. 不,没有这样的方式。 It would be possible in php but not in C#. 可能在PHP中,但不在C#中。

You should change your approach away from properties in this case. 在这种情况下,您应该改变您的方法远离属性。

UPD: Probably you could use something like this for every property (except for it's obvious weakness): UPD:可能你可以为每个属性使用这样的东西(除了它明显的弱点):

public class Prop
{
    Resource _res;

    public Prop(Resource res)
    {
        this._res = res;
    }

    public string Value
    {
        get
        {
            return LocaleHelper.GetRessource(_res);
        }
        set
        {
            if(_res == null)
                // This is a weak point as it's now
                // as it wont work
            else
                _res.DefaultValue = value;
        }
}

You could implement a single indexed property, giving you one of the following two syntax choices based on your preference. 您可以实现单个索引属性,根据您的偏好为您提供以下两种语法选择之一。 The code would basically be a function that accepts the specifically named resource and returns the right content. 代码基本上是一个接受特定命名资源并返回正确内容的函数。

Travel t = new Travel();
string x = t["Name"];
    or 
string x = t[Travel.Name];

You could make your life easier by encapsulating your getter and setter logic in a base class and then simply calling those methods from any new properties you create (simply acting as thin wrapper around those methods). 通过将getter和setter逻辑封装在基类中,然后从您创建的任何新属性中调用这些方法(简单地充当这些方法的瘦包装器),您可以使您的生活更轻松。 Here's an example: 这是一个例子:

public class Travel : LocalizedRessourceSubscriber
{

    private Ressource<string> Ressource1 = null;
    private Ressource<string> Ressource2 = null;

    public String TravelName { 
        get { return GetRessource<string>(Ressource2); }
        set { SetRessource<string>(Ressource1, value); } 
    }

    public String TravelDescription {
        get { return GetRessource<string>(Ressource2); }
        set { SetRessource<string>(Ressource2, value); } 
    }

}

public class LocalizedRessourceSubscriber
{

    protected T GetRessource<T>(Ressource<T> Source)
    {
        return LocaleHelper.GetRessource<T>(Source);
    }

    protected void SetRessource<T>(Ressource<T> Source, T Value)
    {
       (Source ?? 
           (Source = new Ressource<T>())
                ).DefaultValue = Value;
    }

}

...This way, there is very little logic in your properties and you are repeating less code. ...这样,您的属性中的逻辑很少,并且您重复的代码更少。 This assumes the following classes (which I mocked as genericized): 这假设以下类(我嘲笑为通用化):

public static class LocaleHelper
{
    public static T GetRessource<T>(Ressource<T> Source)
    {
        return default(T);
    }
}

public class Ressource<T>
{
    public T DefaultValue { get; set; }
}

That doesn't make sense. 这没有意义。 using propertys the way you currently have them, you can simply write: 使用propertys就像你现在拥有它们一样,你可以简单地写:

   Travel t = new Travel();
   string tvlName = t.TravelName;    
   string desc = t.TravelDescription;

If you changed to the way you want you'd have to specify the parameter as well 如果您更改为您想要的方式,则还必须指定参数

   Travel t = new Travel();
   LocalizedString tvlName = t.TravelName([someresopurcedesignator]);    
   LocalizedString desc = t.TravelDescription([someresopurcedesignator]);  

all you could do is make a "propertyBag" emulator 你所能做的就是做一个“propertyBag”模拟器

   public class Travel 
   {
       private LocalizedString props = new LocalizedString();
       public LocalizedString Propertys
       {
          get { return props; }
          set { props = value; }
       }

   }

   public class LocalizedString // this is property Bag emulator
   {
       public string this[string resourceName]
       {
           get{ return LocaleHelper.GetRessource(resourceName); }
           set{ LocaleHelper.GetRessource(resourceName) = value; }
       }
   }

You would access this like this: 您可以这样访问:

   Travel t = new Travel();
   t.Propertys[NameResource1] = "Bob Smith";
   t.Propertys[DescriptionResource2] = "Fun trip to discover the orient";
   string tvlName = t.Propertys[NameResource1];    
   string desc    = t.Propertys[DescriptionResource2];    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM