Generate custom setter using attributes - c#

In classes whose instances I persist using an object database, I keep having to do this:
private string _name;
public string Name
{
get { return this._name; }
set { _name = value; this.Save(); }
}
whereas I would much rather type this:
[PersistedProperty(Name)]
private string _name;
where the PersistedProperty attributes generates a Getter and Setter just like the default [Property()] attribute, except I want to add a line of code to the generated Setter.
Is there a way I can create an attribute which does this? Hopefully , which works with Intellisense.
How does the default [Property()] attribute even do it's stuff? If I saw the code I could graft that...
Note: I am actually doing this in Boo, but thought I'd give c# code as more people might be willing to answer that, however, if there is a Boo specific solution, I'm all ears!
Update:
My aim was simply to reduce typing and clutter. It turns out the simplest way of doing this was with a script which generates partial classes based on markup in my classes.
Auto-generating source code from markup (in tandem with partial classes) is easy, and actually looks like an extremely promising way to get round some of the problems we normally try to solve with inheritance and generic types.

This requires aspect oriented programming. While not directly supported in .NET, it can be done via third party tooling, such as PostSharp.
For intellisense to work, however, this must be done in a library, as the (final) compiled code will be unrolled into the full property getter/setter.

Not easy to implement using attributes IMO.
Maybe you could use another approach, such as an extension method:
// Extension method that allows updating a property
// and calling .Save() in a single line of code.
public static class ISaveableExtensions
{
public static void UpdateAndSave<T>(
this ISaveable instance,
Expression<Func<T>> propertyExpression, T newValue)
{
// Gets the property name
string propertyName = ((MemberExpression)propertyExpression.Body).Member.Name;
// Updates its value
PropertyInfo prop = instance.GetType().GetProperty(propertyName);
prop.SetValue(instance, newValue, null);
// Now call Save
instance.Save();
}
}
...
// Some interface that implements the Save method
public interface ISaveable
{
void Save();
}
...
// Test class
public class Foo : ISaveable
{
public string Property { get; set; }
public void Save()
{
// Some stuff here
Console.WriteLine("Saving");
}
public override string ToString()
{
return this.Property;
}
}
...
public class Program
{
private static void Main(string[] args)
{
Foo d = new Foo();
// Updates the property with a new value, and automatically call Save
d.UpdateAndSave(() => d.Property, "newValue");
Console.WriteLine(d);
Console.ReadKey();
}
}
It's type-safe, autocompletion-friendly, but it requires more code than just .Save() in all setters, so not sure I would use it actually...

Related

C# Read attributes from Generic class without instance

Problem Description
I'm trying to implement a very specific sort of cache of objects that I may not be able to instantiate directly (private constructors for instance)
What I want to do is read some information about the particular class, preferably through some kind of interface (which sadly doesn't support static methods defined for every subclass)
In other words:
public class Data
{
public static bool Attribute1() => False;
private Data(...) { ... }
}
public class Cache<T> // T is for instance Data
{
void SomeMethod()
{
bool Value = T.Attribute1()
...
}
}
It's fine if I can make T inherit from some base class or some interface, and to get the attribute through some sort of method or directly. It is very important though that I can
Program multiple data classes A and B, where A.Attribute1() is different from B.Attribute1()
Get the attribute from the data class type without instantiating the data type
Current Solution
I do currently have a solution in the shape of a registry built when the static objects are initialised, like this:
class CacheAttributesRegistry
{
static RegisterAttributes(Type T, bool Attribute1, ...) { ... }
}
class Data
{
static Data() { RegisterAttributes(typeof(Data), true, ...); }
}
class Cache<T>
{
void SomeMethod()
{
bool Value = CacheAttributesRegistry.Attribute1(typeof(T));
}
}
It does exactly what I want, but I'd prefer avoiding a static constructor in every data class, also I don't want it to be possible to accidentally call RegisterAttributes at runtime.
Preferably I'd also avoid reflection because I'd like it to be obvious how to set the attributes for a class without the code magically inferring it in the background.
Am I missing some option or have I just reached some language limitations?

Access a hidden property from static method

Given the following
class BaseClass
{
public int Property {get; protected set;}
}
class DerivedClass : BaseClass
{
public new int Property {get; set;} //Hides BaseClass.Property
public static DerivedClass Build()
{
var result = new DerivedClass
{
Property = 17;
//base.Property = 17; // this doesn't compile
}
//((BaseClass)result).Property = 17; // this doesn't compile
}
}
Is there any way to set BaseClass.Property from a static method inside the DerivedClass.
Reflection or Unsafe code is not what I want! I want a non hacky way of setting something which we do legally have access to, but I just can't work out how to set.
Here is how to access an overridden property from a static method of the class:
Add to the class a new property that accesses the base property:
private double BaseProperty { get => base.MyProperty; set => base.MyProperty = value; }
Use that new property from your static:
var result = new DerivedClass
{
BaseProperty = 17;
}
Here is a situation where the above technique is the cleanest solution I have found.
Consider XAML that refers to a BindableProperty, in a class library.
(In my case, the class library is Xamarin Forms.)
Without changing the property name, I want to decouple the base property (used by code compiled into the library) from the XAML-visible property (in my subclass).
The specific use is making text auto-fit, which X-Forms doesn't yet support.
The detail that is relevant here, is that I have the following BindableProperty declaration:
public new static readonly BindableProperty FontSizeProperty =
BindableProperty.Create("FontSize", typeof(double), typeof(AutofitLabel), -1.0,
propertyChanged: (BindableObject bindable, object oldValue, object newValue) => {
((AutofitLabel)bindable).BaseFontSize = (double)newValue;
});
which uses this private property:
private double BaseFontSize { get => base.FontSize; set => base.FontSize = value; }
What this accomplishes, is to initially set base.FontSize - which will be used by layout logic inside library's Label or other text-containing view - to the value set in XAML. Elsewhere in my subclass, I have logic that lowers base.FontSize as needed, once the available width/height are known.
This approach makes it possible to use the library without altering its source code, yet make it appear, to clients of my subclass, that auto-fitting is built-in.
It wouldn't be valid to change FontSize that is visible to client code - that represents the requested size. However, that is the approach taken by Charles Petzold in XF Book Ch. 5 "EmpiricalFontSizePage". Also, Petzold has the page itself deal with the auto-sizing - which is not convenient.
The challenge is the need to tell the library what actual FontSize to use.
Ergo this solution.
All other approaches I've found online require complex custom renderers, replicating logic already existing in XF library.
Is there any way to set BaseClass.Property from a static method inside the DerivedClass.
Yes, rethink your design. It is flawed. Hiding a property and then wanting to set the exact same value on the base and derived class? There seems something really wrong.
You don't necessarily need to hide the property, you could override it, but then it wouldn't make too much sense. It seems the only objective you have is to have different access modifiers on your base class and derived class. This goes against OOP rules, and should be avoided.
If you can introduce another intermediate class, then you can obviously do this. But as others have said, it doesn't just have a code smell, it's positively poisonous.
class BaseClass
{
public int Property { get; protected set; }
}
class InterClass : BaseClass
{
protected void DoFunnyStuff(int value)
{
this.Property = value;
}
}
class DerivedClass : InterClass
{
public new int Property { get; set; } //Hides BaseClass.Property
public static DerivedClass Build()
{
DerivedClass result = new DerivedClass
{
Property = 17
//base.Property = 17; // this doesn't compile
};
result.DoFunnyStuff(17);
return result;
//((BaseClass)result).Property = 17; // this doesn't compile
}
}
So DerivedClass does inherit from BaseClass still, but not directly. You can apply various tricks to try to minimize how much other code is exposed to the existence of InterClass.
It seems you want to modify the APIs behaviour in such a way that something which was mutable before should not be mutable any more. So why not defining a new property, which is really immutable and make the existing one Obsolete instead o trying to hide the original property but not hiding it?
class LegacyClass
{
[Obsolete("Use NewMember instead")]
public string ExistingMember { get; set; } // should actually be immutable
public string NewMember { get { ... } }
}
This way you donĀ“t break existing code.
Yes it's possible through reflection: Property hiding and reflection (C#)
No it's not possible in other ways, if you hide a property by design it's because you don't want give access to that from DerivedClass
Reflection allows you to access for particular purpose, it's not an hacky way the use of reflection.
It's an hacky way to access to a property that you have hidden by design.
If you want access in a legal way to a property you should not hide it.

How to pass non-constant values to Attribute

Is there a way around to pass non-constant complex or primitive values to an attribute?
public class SomeClass
{
private SomeOtherClass _someOtherClass = new SomeOtherClass();
private int _somePrimitiveVariable = CalculateSomeValue();
[MyAttribute(InputValue = _someOtherClass)
public void MyMethod()
{
//Some stuff
}
//Or can it be like this?
[MyAttribute(InputValue = _somePrimitiveVariable)
public void MyMethod()
{
//Some stuff
}
}
Attributes are resolved at compile time, so the comments saying "no" are mostly correct.
However, if you can't rework your design, there are limited workarounds. If this is a universal property you wish to set (that will apply to every user of the attribute), your best bet might be having an initializer method in your code call a configuration method on the attribute. This would look vaguely similar to Can C# Attributes access the Target Class?. Ugly, but might work in specific circumstances.

c# getters setters style

I'm working on some code where there is lots of code like this:
private int x;
public void SetX(int new_x)
{
this.SetXValue(new_x);
}
private void SetXValue(int new_x)
{
this.x = new_x;
}
and similarly with properties:
private int x;
public int X
{
get { return this.GetX(); }
}
private int GetX()
{
return this.x;
}
What i don't get is why the need for the private methods which do the actual work, i.e. why not just have methods like this instead:
public void SetX(int new_x)
{
this.x = new_x;
}
public int X
{
get { return this.x; }
}
is it just the other persons personal choice or is there some good reason for using the first way?
(i typed above code manually so sorry if any mistakes but you should hopefully see what i'm trying to say)
Cheers
A
There's no reason for code like that as far as I can see. If you're not doing anything with the new values (like processing/checking before storing) and you're writing C# 3.0 you can actually just shorthand it it to this:
public int MyProperty { get; set; }
The compiler creates the backing store for you and you can just reference:
this.MyProperty
...inside your class. You can also create get-only properties like:
public int MyProperty { get; private set; }
All of which I think is pretty neat!
Why don't you use the Getters and Setters directly to implement your logic? I don't understand the need for additional methods unless you have extra parameters that influence the setter's behavior:
private int myVar;
public int MyProperty
{
get
{
return myVar;
}
set
{
myVar = value;
}
}
public void SetMyPropertySpecial(int a, string reason)
{
Console.WriteLine("MyProperty was changed because of " + reason);
this.myVar = a;
}
Update:
Indeed, this person seems to like having more lines of code, but the structure is utterly useless. Stick to .NET standards using Getters and Setters (see MSDN)
No, there is no reason for doing this, it looks liks someone was paid by lines of code.
So, yes, you're right, this is just the other persons personal choice, and it's not a very good one.
A general rule of thumb is to use properties for simple get/set operations and get/set methods when there is a relevant part of logic needed to get/set a value (e.g. validation during set or database access during get).
So if the actual code is really as simple as in your example just use properties and do the work in their getters/setters.
If the actual code is more complex replace the properties (at least the setters) by methods as in your third example.
One possible reason would be that the properties can have login that should be executed only when the property is set externally and calls from inside the class do not execute the whole logic but only the logic in the private method. Of course it makes no sense to make these methods in advance because introducing them later will not change the contract of the class. Chances are that whoever wrote this code was new to C# and did not understand what properties do.
I think it must be an old Java developper that did this.
The .Net way is
private int _foo;
public int Foo
{
get
{
return _foo;
}
set
{
_foo = value;
dostuff();
}
}
That's very bizarre, there's no justifiable reason for doing that. Please refactor that code. There's also no need for a SetX method as setter can be included in properties. e.g.:
public int X {get; set;}
i may be missing something here, but this looks a bit mad to me!
You can achieve the same by either using automatic properties or properties with backing fields. here's a good description of both: http://weblogs.asp.net/dwahlin/archive/2007/12/04/c-3-0-features-automatic-properties.aspx
Yes, that is fine only if the SetValue is private or protected and is doing more than just setting a value.
I am working on a project where we do a lot of those things. That is because we are doing more than just setting a value (value checks, state checks etc.)
Having a public setter and a public SetValue does not make sense at all and will confuse your consumers as to what setter to use.
Here is another scenario where we use this kind of design:
public abstract class A{
protected virtual void SetValue(object value);
public object SomeObject{
set{SetValue(value);}
}
}
In this case, we want class A to delegate setting/checking that value to whatever class inheriting from it.

How can one type access a private setter of another type's property?

All I need is a way to make a property of one class only 'settable' from one other class (a sort of manager class).
Is this even possible in c#?
My colleague 'reliably' informs me that I have a design flaw, but I feel I should at least ask the community before I concede defeat!
No, it's not really possible to do this in any clean way in C#. You probably have a design flaw ;-)
You can use the internal modifier, which lets all types in the same assembly access the data (or nominated assemblies if using [InternalsVisibleTo] - but no: there is no friend equivalent in C#.
For example:
public string Foo {get; internal set;}
You have a design flaw. Also, don't be paranoid about data hiding. Here's 3.5's way to do it:
class Program
{
static void Main(string[] args)
{
Managed m = new Managed();
Console.WriteLine(m.PrivateSetter);
m.Mgr.SetProperty("lol");
Console.WriteLine(m.PrivateSetter);
Console.Read();
}
}
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(s => PrivateSetter = s)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
}
public class Manager
{
private Action<string> _setPrivateProperty;
public Manager(Action<string> setter)
{
_setPrivateProperty = setter;
}
public void SetProperty(string value)
{
_setPrivateProperty(value);
}
}
Here's how we'd do it in pre-lambda days:
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(this)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
public class Manager
{
public void SetProperty(string value)
{
m.PrivateSetter = value;
}
private Managed m;
public Manager(Managed man)
{
m = man;
}
}
}
The best way to do it would be:
/// <summary>
/// Gets or sets foo
/// <b>Setter should only be invoked by SomeClass</b>
/// </summary>
public Object Foo
{
get { return foo; }
set { foo = value; }
}
When you have some complex access or inheritance restriction, and enforcing it demands too much complexity in the code, sometimes the best way to do it is just properly commenting it.
Note however that you cannot rely on this if this restriction has some security implications, as you are depending on the goodwill of the developer that will use this code.
You cannot do that on that way, but you can access a property's setter method from a derived class, so you can use inheritance for the purpose. All you have to do is to place protected access modifier. If you try to do so, your colleague is right :). You can try doing it like this:
public string Name
{
get{ return _name; }
protected set { _name = value; }
}
keep in mind that the set method of the property is only accessible from the derived class.
Or you could have these two classes in an assembly alone and have the setter as internal. I would vote up for the design flaw though, unless the previous answer by milot (inheriting and protected) makes sense.
You could do:
public void setMyProperty(int value, Object caller)
{
if(caller is MyManagerClass)
{
MyProperty = value;
}
}
This would mean that you could use a 'this' pointer from the calling class. I would question the logic of what you're attempting to achieve, but without knowing the scenario I can't advise any futher. What I will say is this: if it is possible to refactor your code to make it clearer, then it is often worthwhile doing so.
But this is pretty messy and certinly NOT fool-proof ... you have been warned!
Alternativly...
You could pass a delegate from the Class with the Property (Class A) to the Manager Class (Class B). The delegate can refer to a private function within A to allow B to call that delegate as any normal function. This precludes that A knows about B and potentially that A is created before B. Again... messy and not fool-proof!
You can achieve to this by making a Public property in your "settable class" that will inherit from the real class that will have a protected property... this way only the inherit class can SET and not class that doesn't inherit. But the drawback is that you will require to have an inherit class...
Reflection, though I would agree that having to do this just to get around an access modifier is probably an indication of a bad design.
public class Widget
{
private int count;
public int Count
{
get { return this.count; }
private set { this.count = value; }
}
}
public static class WidgetManager
{
public static void CatastrophicErrorResetWidgetCount( Widget widget )
{
Type type = widget.GetType();
PropertyInfo info = type.GetProperty("Count",BindingFlags.Instance|BindingFlags.NonPublic);
info.SetValue(widget,0,null);
}
}
The reason this is a design flaw is because it seems muddled between the scope of the two objects.
The properties of a class should be accessible in the context of that class, at least internally.
It sounds like the settable property on your item class is really a property of the manager class.
You could do something similar to what you want by closely coupling the two classes:
public class MyItem {
internal MyItemManager manager { get;set; }
public string Property1 {
get { return manager.GetPropertyForItem( this ); }
}
}
Unfortunately this isn't great design either.
What your looking for is what C++ calls a Friend class but neither c# or vb has this functionality. There is a lot of debate as to the merit of such functionality since it almost encourages very strong coupling between classes. The only way you could implement this in c# would be with reflection.
If your goal is to have a class Foo let some property (e.g. Bar, of type Biz) to be changed by some other object, without exposing it publicly, a simple way to do that is to have an instance of Foo which is supposed to be changeable by some other object to pass that other object an Action<Biz> which points to a private method that changes Bar to the passed-in value. The other object may use that delegate to change the Bar value of the object that supplied it.
If one wishes to have give all instances of some type Woozle the ability to set the Bar value of any instance of Foo, rather than exposing such abilities on a per-instance basis, one may require that Woozle have a public static method Woozle.InstallFooBarSetter which takes a parameter of type Action<Foo, Biz> and one of type Object. Foo should then have a static method WoozleRequestBarSetter which takes an Object, and passes it to Woozle.InstallFooBarSetter along with an Action<Foo,Biz>. The class initializer for Woozle should generate a new Object, and pass it to Foo.RequestBarSetter; that will pass the object to Woozle.InstallFooBarSetter along with a delegate. Woozle can then confirm that the passed-in object is the one that it generated, and--if so--install the appropriate delegate. Doing things this way will ensure that nobody but Woozle can get the delegate (since the delegate is only passed to Woozle.InstallFooBarSetter), and Woozle can be sure its delegate comes from Foo (since nobody else would have access to the object that Woozle created, and Woozle.InstallFooBarSetter won't do anything without it).
if it is a design flaw depends on what you want to do. You could use the StackTrace class from System.Diagnostics to get the Type of the class setting your property and then compare to the type you want to allow setting yor property..but maybe there are better ways for performing something like this (e.g. boxing)

Categories