Can Attributes be used for automatic change notification/logging? - c#

Is there a way to do this:
class Example {
[ChangeNotification]
private int field;
}
Such that changing the value of "field" would automatically get logged, generate an event, etc?

No, attributes are type specific, not instance specific.
But you can implement INotifyPropertyChanged on all you objects and have some class listen to all the events and do the logging.

At first view, I would better recommend that you implement the INotifyPropertyChanged interface, as an Attribute is type specific.

You can do something similar (at least to a property, but not to a field) via Aspect oriented programming. However, this requires the use of a program like PostSharp, which actually rewrites the code inline based on the attribute.
Typically, this is used to implement INotifyPropertyChanged on a property. However, there are rewrite rules for logging and other features available.
This won't work for a field, however. It does work for a property, since the rewriter can add code to the property set method, but a field is handled directly by the CLR.

yes it's possible with postsharp using OnFieldAccessAspect
http://www.sharpcrafters.com/forum/Topic2244-4-1.aspx

Related

Force a Subclass to Define Extra Fields in C#

My company has a base database model class that is subclassed by particular instances of our product. The class represents primary keys in a database. The base class has a field, which we'll call AlwaysPresent, which is common to all instances of the product and is not used in querying.
abstract class BaseClass
{
private string AlwaysPresent
}
But it is a requirement that subclasses add at least one more field, as we will use reflection later to treat those other fields as database column names for a query. If there are no other fields, we can't query.
So, my question: is it possible to use C#'s reflection capabilities to force a non-abstract subclass to define new fields without specifying their names?
I am a Python programmer by trade, and I know exactly how to solve this kind of problem in Python using metaclasses. To my knowledge, C# does not have metaclasses. And I cannot raise an exception in the base class constructor, because (for various reasons) we don't use constructors for these classes (just initializers), and even if we did the base class constructor could be overridden.
Reflection cannot be used to force something. At least not at compile time. Via reflection you can read how a type is. In your case you can probably check its fields and throw an exception if required at run time.
In any case usually it is much better to use properties instead of fields. Properties are more extensible and better to hide the internal structure of a class.
A common way to enforce a specific design (properties or methods definition) of a class is to use interfaces.You can have also a class that implement more than one interface.
If properties names or fields are not know when designing the interface you cannot enforce your requirements at compile time but only at run time.
Another common c# technique is to decorate properties or fields with attributes. Maybe you can create a custom attribute and at run time check for fields with that attribute (always with reflection).
This can be done with aspects, specifically PostSharp. It allows you to execute custom code during compilation (in fact, it hooks on postcompile action) in the CompileTimeValidate:
http://www.postsharp.net/blog/post/Architectural-Validation
You can of course replace PostSharp with any custom code triggered on postcompile at build-time.
Turns out this is not a feature in C#, but you can write it like this to force people to implement it
abstract class BaseClass
{
private abstract string GetAlwaysPresent();
}

Do INotifyPropertyChanged users use reflection to fish out the value from the actual property?

When I implement INotifyPropertyChanged does the code using the event use reflection to fish out the value from the actual property? Or use it use something other than reflection like IL emit?
No, because the PropertyChangedEventArgs raised by the event only contains the sender of the event and the name of the property which changed on the sender. If you would like access to the old or new value, you must retrieve them on your own.
As for what the Framework uses to determine what the value is currently, that will depend on the context used (one option is a PropertyDescriptor from a TypeDescriptor).
If you're talking about how the WPF data binding infrastructure gets to the data, it does some fairly sophisticated things. I can only speak to what I've seen from the disassembled source as I last saw it, as these are implementation details and subject to change. For non-Dependency properties (the ones that are typically notified using INotifyPropertyChanged), the system uses Reflection internally, but caches the references. The Binding Path property string is represented as a PropertyPath and there is an internal PropertyPathWorker that does the work of parsing this path and setting up the actual binding. This creates a cached 'list' of references, since the property path can be rather complex, such as Something.SomeProperty[0].SubProperty.(Grid.Row). The binding system allows for any of the values along the chain to change and, if any of them changes, has to reevaluate the downstream references.
In short, it's designed to be efficient, but doesn't use Emit, as it has to support re-computation of the references based on changes inside a complex path. This can be further complicated by the dynamic nature of the binding, since the actual Type of a reference along the chain can change. For instance, Something may be of type Object, so any object that has a SomeProperty IList<T> property is a valid binding target. If the Type changes, it has to re-reflect to bind to the new property on the new Type.
The client code does whatever it wants to.
Typically, InotifyPropertyChanged is consumed by the databinding infrastructure, so it will get property values using PropertyDescriptors.
INotifyPropertyChanged does nothing but tells the class to raise event. When or which property will raise event depends on your code and how you implement it. You can use reflection or Attribute (ContextBoundObject) or can use attribute to inject IL code inside setter method of property

Attributes creating fields in C#

Alright, so after a few hours of me playing around to no avail, I built a model:
[AttributeUsage(AttributeTargets.All)]
public class PublicAttribute : System.Attribute
{
public enum Access { Public, Private }
public PublicAttribute(string Name, Access acs)
{
}
public PublicAttribute(string Name, Access acs, Action get, Action set)
{
}
}
So that if somebody were to do something like this:
[Public("PublicProperty", PublicAttribute.Access.Public)]
private string PrivateProperty = "hello";
or
[Public("PublicProperty", PublicAttribute.Access.Public, ()=>{return PrivateProperty;}, ()=>{PrivateProperty = value})]
private string PrivateProperty = "hello";
and then if somebody was trying to access PrivateProperty, they could just go:
ContainingClass.PublicProperty = //ect
"PublicProperty". and that is because of the attribute, and it would use those get/set accessors.
What I'd like to know:
Is this even possible?
Is there something that already does this?
If its possible, (even if there is something else) How do i do this?
Basically no to all 3, as C# is a strongly typed language. Even with duck typing what you're trying to achieve doesn't fit the language.
The attributes you've written allow you to interrogate the properties that have those attributes in the class, but you still need to use Reflection to discover which properties of the attribute class are set. The syntax you want to use is checked at compile-time.
No, this is not possible using attributes. Properties are part of the class metadata emitted by the C# compiler, and the C# compiler does not consider custom attributes.
You may be able to do this by using a post-processor such as PostSharp, which can rewrite your assembly after the fact, and can be instructed to consider custom attributes. However, you still wouldn't be able to include a delegate in the attribute: the set of types that can be stored in attribute state is extremely limited.
Microsoft made the WebMethodAttribute in a way reminiscent of what you're trying to describe making it represent more permission than C# public, effectively making a method available outside the application domain to the entire Internet (a very global scope). You might read it to get real implementation insight and ideas.
But you're hitting it very simply. You'll have to program some infrastructure to make it work. It's not automatic and you don't have access to Microsoft's source code for all the details.

Is the implementation of Auto Properties in the spec?

Can I rely on the fact that the underlying field to a property named Foo is called "k__BackingField" ?
No, in short.
And for this very reason, auto-properties are pain when used with field-based serializers like BinaryFormatter (I'm sure I might have mentioned that here before ;-p).
See: Obfuscation, serialization and automatically implemented properties for some thoughts on this (and a solution).
That the spec does not specify the backing field's name (with good reason - you shouldn't take a dependency on it).
You should investigate to see whether the Mono compiler does the same thing for example.
Sanity checking that the field had the CompilerGeneratedAttribute applied to it would be a good idea.
Note that explicit interface implementations would come out (currently) as:
<Full.Namespace.To.Interface.IBlah.Foo>k__BackingField
So code which is trying to serialize a specific aspect of a class in this fashion could be mislead.
If you wanted to be really belt and braces about your code you could use a library like mono's Cecil to inspect the get function of the property and determine the field used.
Of course not. That would be a private implementation detail.
And why on Earth would you want to know?
I don't think so. If you need the backing field, use a 'regular' property.

Overriding a read/write property to make it readonly

I'm writing a custom control in C# based on TextBox. I want the Text property of my control to be read-only (since only certain values are allowed in the textbox and I don't want the calling program to be able to put invalid values in there.)
I don't see how to do this. If I use public override Text {} the compiler inserts default get and set accessors. If I comment out the set accessor, the code compiles and runs, which I assume means the base accessor is being used. If I put readonly in the definition of my property, the compiler throws an error.
Any help would be greatly appreciated.
The issue here is that by trying to make a read/write property read-only, you're violating the contract of your base class. Your base class explicitly states that this property can be both retrieved and modified. Derived classes cannot break the contracts of their base classes, otherwise polymorphism would fail. Remember that if B derives from A, anywhere an A object is accepted, B must perform.
If that should not be the case for the derived class, then I would first question the design -- should this truly be derived from the base class? Is this truly an "is-a" relationship?
Assuming that we passed that test and truly should be derived, one approach -- which I don't personally like, but will share anyway -- may be to simply have the setter throw an exception. I personally don't like this, it still violates the contract, and feels like an excessive amount of cognitive friction in using your derived class, but if you truly have that solid a reason to do so ... well ... OK, I guess. But be sure you know WHY you're hacking around this.
But go back to the first point: Is this truly a scenario where a derived class is the right answer, from a design standpoint? Without seeing your code, my gut reaction is a no.
EDIT
Somehow in my initial read of this, I missed the fact that we're talking about a UI control here. I stand by what I wrote above this edit, in the general property overriding case. However, in the case of a UI control, where the polymorphism opportunities (I hope) will be somewhat limited, and where the need may well justify this design, then my recommendation would be to have the Text property setter throw an exception.
A better design, in my opinion, would be composition. Make a user control, add the TextBox to the user control design surface with Dock=Fill, and then expose a new Text property which is readonly. You can also now expose only those properties you really want to.
You have to hide the base property by declaring Text with the "new" keyword.
public new string Text { get; private set;}
You can't change access rights with an override, so you cannot use the override keyword, as you've seen. This way will "hide" the base implementation of Text, which isn't always a good idea, but as long as you know the risks it will work for you.
public new string Text { get; private set;}
Aside from others comments on overall design issues (which John Ruby explains nicely), you could always just override the setter to do nothing or throw an exception.
I don't think that shadowing the property is the right answer, because any reference through the base will still work. Since the property is virtual, you can override it and implement a setter that ignores changes or throws an exception. I know it seems less clean, but it has the advantage of actually working.
edit
Looks like Yuriy Faktorovich made the same suggestion before I could.
I think John Rudy may have a point here. Inheritance is not the answer to everything. If what you need to do is restrict a textbox so that only valid values can be accepted then perhaps you want to use a validation control to make sure that only certain values are allowed.
This way you get the behaviour you want by making use of the components Microsoft have provided us with. No inherited class necessary.
Edit: If you create a subclass every time you want to modify the behaviour of a UI control you will quickly have an unruly inheritance hierarchy on your hands. For this reason I would suggest you consider composition to modify UI controls.

Categories

Resources