How Can an Attribute Class Reference the Instance that Uses It? - c#

Let's say I have an attribute class:
public class MyCustomAttribute : Attribute
{
// do stuff
}
And I use this attribute on class properties:
public class MyModel : BaseModel
{
[MyCustom]
public string Name { get; set; }
}
Is there a way, within the code of MyCustomAttribute, to reference the instance of MyModel on which it's being used?
Ultimately I'm just experimenting with AOP (using PostSharp) to create attributes to track when a model is dirty. So if BaseModel has an IsDirty property then I'd like to be able to do something like this with PostSharp:
public class TrackDirtyPropertyAttribute : OnMethodBoundaryAspect
{
public override void OnSuccess(MethodExecutionArgs args)
{
someReferenceToTheObject.IsDirty = true;
}
}
I've tried passing a reference into the attribute's constructor:
public class TrackDirtyPropertyAttribute : OnMethodBoundaryAspect
{
private BaseModel _currentObject { get; set; }
public TrackDirtyPropertyAttribute(BaseModel currentObject)
{
_currentObject = currentObject;
}
public override void OnSuccess(MethodExecutionArgs args)
{
_currentObject.IsDirty = true;
}
}
However, when I use it:
[TrackDirtyProperty(this)]
public string Name { get; set; }
It tells me that this is not available in that context.

You should do it like this:
public class TrackDirtyPropertyAttribute : OnMethodBoundaryAspect
{
public override void OnSuccess(MethodExecutionArgs args)
{
((BaseModel) args.Instance).IsDirty = true;
}
}

Your constructor won't work (at least not with this) because the attribute constructor arguments must be accessible in a static context. And by default you can't simply access the utilising type's instance - which makes sense, since this is essentially metadata (applied to the definition, not instances - the instances just come 'strapped' with it). So you can natively access the attributes of a type, but not the instances of the type used by an attribute.
You could probably get it through some contrived reflection and so forth (I'm not even going to venture into thinking about this), however, not so elegantly one way as the other.
On another note, it makes little sense to me to store the state of an element within an attribute - this isn't persistent enough. Making calculations to retrieve a value (say you did get a hold of the instance, and managed to run some logic to determine if it 'is dirty' and provide a 'real time' value in that sense) yes, but using it to persist information applied to it after the fact of declaration seems futile, since which instance of the attribute is it to persist in anyway? In any case, and regardless of what I might have totally missed in saying this, this is what the instances themselves are for.

Related

Abstract singleton inheritance with multiple sub-classes

Continuing with the answer given here, is there a way to allow MyChildSingleton to be abstract, and then let it's sub-classes define their own constructors? An example of what I would like to do:
public abstract class SingletonBase<T>
where T : SingletonBase<T>, new()
{
private static T _instance = new Lazy<T>(() => new T());
public static T Instance
{
get
{
return _instance;
}
}
}
public abstract class DefaultConfigData: SingletonBase<DefaultConfigData>
{
// This class won't compile since it's abstract, and SingletonBase<T>
// has a new() restriction on T
// Also, this class is immutable and doesn't change state
public virtual string SomeData { get; } = "My Default Data String";
public virtual double MoreData { get; } = 2.71;
public virtual double SomeFunction(double num)
{ return num + 2*MoreData; }
public DefaultConfigData() { ; /* nothing to do here */ }
// Another 50 or so default values/functions...
// enough to be tedious to redefine in multiple places,
// and adding a constructor that takes every value would be ridiculous.
// It would be possible to encapsulate this data, but I'm not
// yet sure how this should be done, so I haven't gone there yet
}
public class SpecificConfigData1: DefaultConfigData
{
public override string SomeData { get; } = "A Different String";
public SpecificConfigData1() { ; /* nothing to do here */ }
}
public class SpecificConfigData2: DefaultConfigData
{
public override double MoreData { get; } = 3.14;
public SpecificConfigData2() { ; /* nothing to do here */ }
}
// Downstream developers may need to define additional ConfigData classes
public class Library
{
public static double doSomething(DefaultConfigData data) { return data.MoreData + 2.0; }
}
public class Program
{
private readonly DefaultConfigData data;
public Program(bool choice)
{
data = (choice) ? SpecificConfigData1.Instance : SpecificConfigData2.Instance;
}
public static void Main()
{
Program prog = new Program(/*run-time user input here*/);
Console.PrintLine(Library.doSomething(prog.data));
}
}
Using a singleton pattern seemed like a good idea, because for each specific subclass the data only needs to exist in one place, and since it's immutable this avoids most of the issues associated with singletons (global mutable state, etc.). Providing the singleton functionality in an abstract base class would avoid the boilerplate of putting the private instance and public get property, which is what I'm doing now in each sub-class. This really isn't too onerous a requirement, I'm sure I could live with it.
I don't want to make DefaultConfigData and it's data static, because then I can't inherit from it and have my library functions know how to interact with it (no support for metaclasses in C#). Also, I don't want to use an interface, because so much of the functionality is shared, and I couldn't define that in the interface.
I would also welcome comments on alternative approaches, if the one I'm trying to do can't be accomplished, or if another way is simply easier. I know that a factory pattern could also work here, and that's something I intend to try eventually.
Last, why is this even an issue? Why wasn't the decision made to let abstract classes satisfy the new() requirement, provided that any of their sub-classes also satisfy a new()?
Note that my "users" are other internal developers/my future self. Source code is usually the deliverable, and pushing checks to run time are ok in this environment.
The easiest solution I can think of is using a factory pattern. The other solution is you need to keep DefaultConfigData class generic, like:
public abstract class DefaultConfigData<T>: SingletonBase<T>
where T : DefaultConfigData<T>, new()
{ }
The problem with that is when you want to use DefaultConfigData anywhere, you have to make that method or class generic, like the doSomething method:
public static double doSomething<T>(DefaultConfigData<T> data)
where T : DefaultConfigData<T>, new()
{
return data.MoreData + 2.0;
}
And as you can guess, that can get really annoying. So, back to the factory pattern:
public static class MyFactory<T>
{
private static Lazy<T> _instance = new Lazy<T>(CreateUsingReflection);
public static T Instance
{
get
{
return _instance.Value;
}
}
private static T CreateUsingReflection()
{
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
ConstructorInfo ctor = typeof(T).GetConstructor(flags, null, Type.EmptyTypes, null);
return (T)ctor.Invoke(null);
}
}
And, you can use it like so:
SpecificConfigData1 scd1 = MyFactory<SpecificConfigData1>.Instance;
Note that none of your classes need to inherit from MyFactory. You are free to create classes that inherit from anything (or nothing), as long as you have a parameterless constructor. You could restrict the T in MyFactory<T> using where T : new(), in which case you will get compile-time guarantee that the class supports a parameterless public constructor, and can avoid reflection by creating the class using just new T(). Without the new() restriction, it can create singletons using a private constructor, but you lose the compile-time checking that a parameterless constructor exists.
Actually, there is another solution. It is much more complex, but it is quite powerful if you use it to its fullest: an IoC container such as Autofac, Unity, and many others. These can help manage your instances, so that you can specify the Types that should be singletons. I won't go over how to use one since that is a whole different topic, and would require multiple paragraphs just to explain the basics.

Is it possible to limit instances of public inner enum or class to its parent class in C#?

I would like to define an enum inside of a class. The class will have a public property of the enum type. I would like classes outside this class to be able to reference this class' enum property, but I don't want other classes to be able to create their own instances of this enum. Is this even possible? Consider this example:
public class MyClassWithEnum
{
public Season MySeason { get; set; }
public enum Season { Winter, Spring, Summer, Fall }
}
public class OutsideClass
{
public void OutsideClassMethod()
{
MyClassWithEnum enumClass = new MyClassWithEnum();
enumClass.MySeason = MyClassWithEnum.Season.Spring; // This should be okay
MyClassWithEnum.Season localSeason = MyClassWithEnum.Season.Winter; // This should NOT be okay
}
}
It seems to me I am left to choose between defining the enum as public and letting any other class create instances of it, or making it private and not being able to set it from outside the class.
You do not instantiate Enums as if it where classes, therefore you cannot prevent someone to use it. With a class you could have a private ctor for example... That's obviously not possible with Enums.
So yes, your assumption is correct, either make it internal or private, or make it public... ;)
Btw, I cannot think about any good scenario where you want to hide the Enum while having a public property using the Enum, even if it where possible to do this.

Reflection, dynamic. How to replace one object with another?

I have an object like this
public class Simple
{
public string Value
{
get { return GetProperty(); }
}
// different methods, fields, events, etc.
}
Possible to replace instance of the class Simple with equal object, but with setter?
How to implement ...
private object Substitution(object simple)
{
object newSimple;
// implementations
newSimple.Value = "data";
return newSimple;
}
To have something like this
public class Simple
{
public string Value { get; set; }
// my methods, fields, events ...
}
I thought to create a class and inherit from SystemObject, then you can create different dynamic properties, but could not do :(
Or maybe try to inherit from this object (how?) and override the properties?
Thanks
You can't change the definition or structure of a loaded type at runtime.
You could, potentially, make a new type that had a similar set of properties and fields, with the property setter added. However, this is going to be of limited use in most cases, as the existing code will not understand the new type (since it's runtime generated), so would still be working off the existing type, which won't be compatible.
Typically, if you need runtime extensibility within a type, there are other options, including using a Dictionary<T,U>, or dynamic with ExpandoObject, or some other mechanism for storing "extra" information within a class that is not known at compile time.
You couuld always use an interface, that only defines a property getter. Then in the implementation have a property setter?
class Program
{
static void Main(string[] args)
{
IMyClass myA = new ClassA{ Property = "Class A" };
Console.WriteLine(myA.Property);
// can't do this
// myA.Property = "New Property";
// can do this
(myA as ClassA).Property = "New Property";
Console.WriteLine(myA.Property);
}
}
interface IMyClass
{
string Property { get; }
}
class ClassA : IMyClass
{
public string Property { get; set; }
}
Failing that, you could do an user defined conversion using the explicit keyword, more info at MSDN

Partially encapsulate a field C#

I want to know if there is any pattern that can overcome this problem:
I have a set of properties that needed to be public to several classes and to other classes they should be only readonly,
the classes must be public.
I do not want to use reflection or any other bad performance makers.
I know I can make them RO and implement logic inside class but I don't think it's good.
Any help?
Inside the current assembly, you can make it internal.
Outside the current assembly, the best you can do is make it available to specific assemblies, via [InternalsVisibleTo].
.NET does not offer more granular "friend" access.
class Person : IReadOnlyPerson {
public string Name { get; set; }
}
public interface IReadOnlyPerson {
string Name { get; }
}
To those classes that should do r/o access - use IReadOlyPerson
Two options:
Make the property internal (not the class) and group the classes into different assemblies.
Use reflection magic.
Sadly, there are no friend classes in C#.
You could try declaring your setters as protected in your base class. Any class that derives it will be able to set it. But any class using the derived class will only see a read-only property.
public class ClassBase
{
public int MyProperty
{
get;
protected set;
}
}
public sealed class ClassDerived : ClassBase
{
public ClassDerived()
{
MyProperty = 4; // will set
}
}
public class ClassUsingDerived
{
public ClassUsingDerived()
{
ClassDerived drv = new ClassDerived();
drv.MyProperty = 5; // will fail
}
}
That is if i understand the question correctly :)

Generic method is picking up type of base class

I have the following classes (trimmed to only show the basic structure):
public abstract class BaseModel {
public bool PersistChanges() {
// Context is of type "ObjectContext"
DatabaseHelper.Context.SafelyPersistChanges(this);
}
}
public static class ObjectContextExtensions {
public static bool SafelyPersistChanges<T>(this ObjectContext oc, T obj) {
// Persist the object using a transaction
}
}
[Persistent("LEADS")]
public class Lead : BaseModel {
// Extra properties
}
public class LeadsController : Controller {
public ActionResult Save(Lead lead) {
lead.PersistChanges()
}
}
My Lead class derives from BaseModel, which contains a method to persist the object's changes to the database using a transaction. I implemented the transactional persist with an extension method. The problem is that by passing this to SafelyPersistChanges in my BaseModel class, the generic T on the extension method is set to BaseModel. However, since BaseModel isn't marked as a persistent object (which it cannot be), the ORM framework throws an exception.
Example:
Lead lead = LeadRepository.FindByNumber(2);
lead.SalesmanNumber = 4;
// Calls "ObjectContextExtensions.SafelyPersistChanges<BaseModel>(BaseModel obj)"
// instead of "ObjectContextExtensions.SafelyPersistChanges<Lead>(Lead obj)"
lead.PersistChanges();
The above block raises the following exception:
Cannot create mapping for type 'SalesWeb.Data.BaseModel' without persistent attribute.
Any ideas?
Extension Methods are statically bound at compile time. At the point in which SafelyPersistChanges is called, this is typed as BaseModel and hence your exception. In order to get the behavior you want, you'll either need to do an ugly if statement with lots of casting or force the call to the derived class.
Make PersistChanges an abstract method. Then implement the call in the derived classes with exactly the same code.
public class Lead {
public override bool PersistChanges() {
// Context is of type "ObjectContext"
DatabaseHelper.Context.SafelyPersistChanges(this);
}
}
Now this will properly be Lead
I would have designed this differently, making "public bool PersistChanges()" call a virtual method, that is overridden in each subclass.
So, you want a "single" implementation, that varies against a type known by the caller. Sounds like a job for Generics.
public static bool PersistChanges<T>(this T source)
where T : BaseModel
{
// Context is of type "ObjectContext"
//static property which holds a Context instance is dangerous.
DatabaseHelper.Context.SafelyPersistChanges<T>(source);
}
You could solve this using the curiously recurring template pattern:
// change your code to this
public abstract class BaseModel<TDerived> where TDerived : BaseModel
{
public bool PersistChanges() {
// Context is of type "ObjectContext"
DatabaseHelper.Context.SafelyPersistChanges((TDerived)this);
// ^
// note the cast here: -----------------------|
}
}
public class Lead : BaseModel<Lead> { }
// the rest of your code is unchanged
That would work, but I'd probably just follow the other suggestions and use a virtual method.

Categories