Accessing instance-level custom attributes in c# - c#

Imagine I have the following code:
class A
{
[UsefulAttribute("foo")]
B var1;
[UsefulAttribute("bar")]
B var2;
...
}
class B
{
public string WriteSomethingUseful()
{
?????
}
}
My question is, what code do it need to put in the ????? such that, when I call var1.WriteSomethingUseful I get an output of foo, and when I call var2.WriteSomethingUseful I get an output of bar?
I've got a feeling this is quite a straightforward question, I think my main issue is that I have worked myself into a state of confusion by thinking about it for too long!!!
Seriously, I have defined UsefulAttribute and realise that part of the code must be a GetCustomAttributes(typeof(UsefulAttribute)...) call. Where I'm getting confused is how to pull these values out on the actual instance, rather than at the type level.
Many thanks,
Pete

This isn't possible. For starters, what if multiple different instances of A have references to the same B? Or what if the same instance of B is referenced by both var1 and var2?
When you set the attribute on the field, you are attaching that attribute to the type of class A, not the instance of class B stored in the field var1.
The normal way to go about this is to store the data as a property of B, set it either via a property setter or a constructor parameter, and then access the property from the WriteSomethingUseful method.

Since your WriteSomethingUseful() method is within the type B, but your attributes are declared within type A you will not be able to access them based on an instance - you simply don't have a reference to A.
The current B instance might not be related to A at all, and without being able to retrieve "the type of the class instance (if any) that contains the current B instance" - which is not possible in C# - there is no general way to do this.

Related

C# - Inside instance method, why can we access static members without using the class name?

This seems counter-intuitive to me. If we have a class Dog with static method CountAllDogs(), C# forbids to call it like this: myDog.CountAllDogs(). (myDog is an object of type Dog).
But if we are inside an instance method Bark(), we can call it simply by using CountAllDogs(). Inside the instance method Bark(), the context ("this") is the object myDog, not the class itself, so I wonder why this is allowed?
"Why" questions are frequently vague, and this one is no exception. Rather than answer your vague and confusing question, I'll answer a different question.
What is the fundamental rule for resolving unqualified names in C#?
The fundamental rule of resolving an unqualified name is search from inside to outside. Suppose you have:
using System;
namespace A {
namespace B {
using C;
class D
{
public static void E() {}
}
class F : D {
public static void G() {}
public void H()
{
Action i = ()=>{};
Now suppose somewhere inside H we have an unqualified name, X. We need to figure out what it means. So we go from inside to outside:
Is there any local variable X? If yes, that's the meaning of X. If not...
Is there any member of F called X?
Is there any member of D -- the base class of F -- called X?
Is there any member of object -- the base class of D -- called X?
Is there any member of B called X?
Is there any member of C -- which B is "using" -- called X?
Is there any member of A called X?
Is there any member of System called X?
Is there any global namespace called X?
(This is a sketch that leaves out a few details, such as how aliases are dealt with and so on; read the specification if you want the details.)
An interesting point here is that base classes are considered to be "more inside" than the lexically containing program element. Members of D are considered to be members of F, so they must be checked before we check B.
That's the fundamental rule. There are also a few extra rules added for convenience. For instance, if we had X() then only invocable members are considered when doing the search. There is also the famous "Color Color" rule, which says that if you have a type called Color and a property of type Color called Color -- because what else would you call it? -- then the name lookup rules for Color are smart about figuring out whether you meant the type or the property, even when that means departing from the fundamental rule of unqualified name lookup.
Now that you know the fundamental rule you can apply it to your situation. Why can you call a static member without qualification? Because the fundamental rule of unqualified name lookup is "search from inside to outside", and doing so finds a static element with that name. If we're inside H and we have G() then G is not a local but it is an invocable member of the enclosing class, so it wins. If we're inside H and we have E() then we find it in D, after failing to find it in H or F. And so on.
When you call an unqualified instance member, same thing. The unqualified name is resolved, and if it turns out to be an instance member, then this is used as the receiver of the member.
To call an instance-member you need an instance of course. In case you´re allready within an instance-member you can of course use the this-reference, which points to the current instance. If you´re on the other side calling your instance-member from outside your class you´d write something like this:
myInstance.DoSomething();
So actually using this as qualifier is redundant, you may simply omit it if you´re within the method.
A static member doesn´t know any instance, thus no this. Adding the class´-name is again redundant information as adding the this-keyowrd to an instance-member.
The compiler should be clever enough to determine that a member is static or not and thus if or of not he needs an instance.
Personally I agree that adding the context in which a member might be invoked is a good thing, which is even forced in Java e.g. This avoids anoying prefixes on variables such as m_ for instance- and s_ for static members. But again the compiler allready knows, it´s just a matter of taste.
So having said this there´s no actual need why this should or should not be permitted as it doesn´t avoid any mistakes not produces any. It´s just a convention-thing to be more strict.

Nested objects issues

I have an object named currHotel. It holds values like:
address
bigImageUrl
Category
Chain
City
and so on
This object contains another object inside it, with different values, named - Ben.Hotel.HotelFinder.BC_Hotel:
How can I access the object Ben.Hotel.HotelFinder.BC_Hotel that's inside currHotel?
It doesn't appear in it, and I need some values from it:
As I understand it, the values that you want to access are on your base class? In that case, check the access modifiers on those fields/properties/methods, and make sure that they are exposed in the way you want.
The simplest (and least safe!) approach is to make everything public but depending on where you are trying to read those fields/properties/methods you may be able to get away with protected (accessible in derived classes) or internal (accessible anywhere in the same assembly) instead.
Edit:
Also remember that there is not really a BC_Hotel object "inside" current, but rather current is a BC_Hotel (since its class is derived from it), so all the fields on that base class are available directly on current, depending on access (as I said above).
your currHotel is an instance of type Ben.Hotel.HotelFinder.BC_Hotel.
From the screenshot, the currHotel doesn't have another property of type Ben.Hotel.HotelFinder.BC_Hotel.

Add some meta data associated to a particular field when I am assigning a value to the field of a class?

I have a class, and I am doing some nifty things with reflection.
Now I have a need to add some meta data associated to a particular field when I am assigning a value to the field of a class using reflection (I don't know what the class will be).
I would like to do this without the clients to my implementation knowing (having to do anything special of their own).
Having a designated "meta" field or object within the class would work, but doesn't feel very elegant since it requires the child class to do something to be "compatible". I would like to dynamically attach this meta information to the existing class, but still allow it to be treated like the same class be the rest of the application. I would like to be able to recover this meta information later.
Class gets passed in
Values get assigned (mapped) via Reflection with
Meta information attached
Class returned
*This process should have no side effects in regard normal operations and the object type of the class. To the general application the class should be the same before and after.
Application does "normal" work with the class (assign values, get values, validate information ,etc.)
Class gets passed back in later
Use the values along with meta information to do something
Broken down to the simplest terms, I am basically looking for a way to "Piggy-back" extra information on any arbitrary class instance without special compile-time modification.
I realize this is an odd problem with some odd constraints, but can it be done?
This applies if you need the extra state per type and not instance
Your best bet is to use a custom attribute against the field.
1) So create the attribute:
[AttributeUsage(AttributeTargets.Field)]
public class MyCustomAttribute : Attribute
{
}
2) Decorate the field:
class MyClass
{
[MyCustomAttribute]
private int _myField;
....
}
3) And then in your reflection:
if(fieldInfo.GetCustomAttributes(typeof(MyCustomAttribute), true).Length>0)
{
...
}
If it has got to be in the instance
If data is to be part of the instance then
either instance needs to allow for its storage
state needs to be stored on a separate class like a dictionary
Second approach is the one first coming to mind and straightforward to do. On the first note, one can
Define state as a separate property that can hold info. This is the one you have suggested and you are not happy with.
Inherit from a base class which provides the extra functionality
Create a generic type, e.g. Metadata<T> which will provide such functionality to all types
I tend to like the third which can encapsulate reflecting the type T and creating necessary placeholders for storing extra state. Main problem with this is you cannot pass the type to methods as a parameter. Which seems that the second solution is the most practical.
I'd be inclined to create a dictionary with the object instances as the keys and the metadata as the values. You'd probably need to be careful to ensure that equality is determined with ReferenceEquals() rather than Equals(). You might also need a compound key comprising the object and the relevant PropertyInfo.
This approach also wouldn't work if the metadata needs to follow the object into some context where the metadata dictionary is not available.

Doesn't this defeat the whole purpose of having read-only properties?

I know how to use properties and I understand that they implicitly call underlying get and set accessors, depending on whether we are writing to or reading from a property.
static void Main(string[] args)
{
A a = new A();
(a.b).i = 100;
}
class A
{
private B _b = new B();
public B b
{
get { return _b; }
}
}
class B
{
public int i;
}
What code (a.b).i = 100; essentially does is that first property’s get accessor returns a reference to an object _b, and once we have this reference, we are able to access _b’s members and change their values.
Thus, in our example, having read only property only prevents outside code from changing the value of a reference variable _b, but it doesn’t prevent outside code from accessing _b’s members.
So it seems that property can only detect whether we are trying to read from or write to a variable ( in our case variable _b ) located on the stack, while it’s not able to detect whether we’re trying to also write to members of an object to which the variable on the stack ( assuming this variable is of reference type ) points to.
a) But doesn’t that defeat the whole purpose of having read-only properties? Wouldn’t it be more effective if properties had the ability to also detect whether we’re trying to access members of an object returned by get accessor( assuming backing field is of a reference type )?
thank you
Immutability is not transitive; you can't expect mutable objects into an immutable accessor to be immutable.
Your reference is read only, not your object.
Imagine a class like this:
public class A
{
private List<int> _myList<int> = new List<int>();
public List<int> MyList { get { return _myList; } }
}
Now, users of the class can add and remove and access items in the list, but they cannot replace the list itself. This is important. It allows you to do things inside the class like assume the _myList member is never null, for example.
Put a more general way, this paradigm allows you do define an interface into your class such that users can use the types in the properties you expose, but they cannot just swap instances of complex types out from under you.
No, it does not defeat the purpose of read-only properties.
It is possible to use read-only properties that don't let the user change the underlying data. For example, you can have your property return a System.Collections.ObjectModel.ReadOnlyCollection even though the underlying type is a List. This, of course, won't prevent the user from changing the properties of the items in the collection.
Of course you can access B.i; it's public. You're thinking that since _b is private, all methods should be private when fetched through A? In that case it's pretty useless as you wouldn't be able to use B for anything.
You ask:
Doesn’t that defeat the whole purpose
of having read-only properties?
But look: your B.i member is a public field.
I ask you, then: what is the purpose of having a public field? It only makes sense if you want users of your code to be able to change that field's value. If you don't want that, it should be a private field, or (if you want to provide read but not write access) a property with a private set accessor.
So there's your answer. private B _b serves its purpose in the code you posted quite well (_b cannot be externally set to something new), just as public int i serves its purpose equally well (i can be externally changed).
Reference immutability is a popular feature request. Too bad its is so dramatically non CLS compliant. Very few languages have this notion, I only know of C++ (but don't get out much).
The key problem that this needs to be enforced by the CLR. C++ doesn't need to enforce this at runtime, only a C++ compiler is required to ensure that const contracts are observed. It has no support at all for language interop, beyond a bolt-on like COM.
This won't fly in .NET, there's little point in declaring a reference immutable and have that verified by the compiler when another language can stomp all over it because it doesn't have the syntax to express immutability. I reckon we'll get it some day, not Real Soon.
As a minor point, you don't have to write (a.b).i = 100; but simply
a.b.i = 100;
Back to your question, I don't think it defeats the purpose. You can still not do the following:
a.b = new B();
because there's no public set(). If you want the member i of class B to be read only, you can do the same thing as you did to member _b of class A by making it private and providing a public get(), but not set(). Off the top my head, doing what you propose might lead to many unexpected consistencies (I'm sure the language designers did not overlook this).
Entirely dependent on the situation, but read only access to a mutable object is a commonly used design. In many cases you simply want to ensure that the object itself remains the same.
Some classes (like String object in Java, and I believe in C# as well) are entirely immutable, where as others are only partially mutable. Consider an ActiveRecord style of object for which most fields are mutable, but the ID is immutable. If your class holds an ActiveRecord in a read only property, external classes cannot swap it for a different ActiveRecord object and thus change the ID, which might break assumptions within your class.
I disagree. Your property is for the class B, not for the members of class B. This means you can't assign a new Object to b. It doesn't mean that B's public members suddenly become private.
readonly applies to the class property, not the object that the property refers to. It keeps you from being able to write a.b = new B();, and that is all it does. It places no constraints on what you can do to the object once you get a reference to it. I think what you are discovering is that readonly make the most sense when applied to value types or immutable class types.
Another use case:
interface INamedPerson
{
String Name { get; }
}
class Bob : INamedPerson
{
public String Name { get; set; }
}
class Office
{
// initialisation code....
public INamedPerson TheBoss { get; }
public IEnumerable<INamedPerson> Minions { get; }
}
Now, if you have an instance of the Office, as long as you don't go cheating with casts, you have read-only access to everyone's names, but can't change any of them.
Ah. Encapsulation does the instantiated class inherit the containing class's access level. Exposing type B as a public property of type A. 'B.i' is public so it should be accessible from outside the same way 'A.b' is public.
A.b returns a reference of a privately accessible type B, however type B has a publicly accessible field i. My understanding is that you can set the i field of B but you can't set the b property of A externally. The B type property of A is readonly however the reference to type B does not define the same readonly access to its fields.
I'm sure you can modify the definition of type B to suit your need for the access level of B's fields or properties.

Passing "this" as an argument - C#

I'm currently playing about with some XNA stuff learning to program AI. Anyway, here's my situation: Class A has a function which takes a reference to an instance of class B, does some stuff to to it, and returns it. Class B contains an instance of Class A, and then calls the function from it.
Example in code:
Class A
{
B classB;
public A()
{
classB = new B();
}
public void Act()
{
this = B.Do(ref this);
}
}
Class B
{
public A Do(ref A classA)
{
//Manipulate
return classA;
}
}
I've tried passing a memberwise clone .. but that didn't work, obviously, because "this" is read-only. I've no idea with this. I'm really stuck. Does anybody have any ideas? I'd ideally like to avoid having to pass every single variable in the object as a separate argument, really.
Andy.
Classes are reference types, so doing
Class B
{
public void Do(A classA)
{
//Manipulate
}
}
should manipulate the object classA references. Then in A,
Class A
{
B classB;
public A()
{
classB = new B();
}
public void Act()
{
B.Do(this);
}
}
Note: "This does have the side effect that the reference of A that you pass cannot be set to null (it will only set the local variable to null)" - JulianR
Your B.Do() method does it (modifying an A) double by using the ref and a return. Neither is needed to modify classA. And because you target this it won't work anyway. You never assign to this, it makes no sense.
So the Simple answer is
class B
{
void Do(A anA) { anA.PublicProp = 1; }
}
But the circular referencing does make it a dubious design.
Is there something specific in //Manipulate that requires you to pass a class reference as ref? And why are you also returning classA as well - that seems to be redundent if you are using ref to begin with.
just remove the ref keyword. you only need ref if you want to change the argument into something else, if you just want to manipulate it, don't use the ref.
I think it would be bad (tricky to understand) if the language allowed you to change this into that, so it disallows what you've tried.
you cannot use "ref" with "this".
Why do you need the parameter to be passed by reference ?
You only need a "ref" parameter if your function must change which object the caller is refering to. If all you need is to manipulate and/or change the fields of the parameter then you do not need a ref parameter.
For more clarity, the whole thing is for behaviours for simple AI (EG chase, guard, evade etc). I'm wanting to pass the entire AI entity to the behaviours so that I can keep the behaviours separate for all entities (Sort of like a single style sheet for multiple web pages). The reason I want to pass the whole object is that some behaviours need certain parts of the object and some don't.
As for why I'm returning .. I don't quite know how I came to that decision. I'll remove it
Thank you very much, Derek E!
I just tested what you said, and it worked fine.
My problem, I think, is that I was thinking that when I passed the argument it made a clone of it and manipulated that instead, like (I think ..) it does in PHP or VB (can't remember which of those I was told it does it in)
Objects are always passed by reference and not by value. That is why we call classes in C# as reference types. Be careful if you are using structures instead since they are value types. A copy of the structure will be passed rather than the original. If you wish to pass the original then you must add the ref keyword. ref is only useful with objects if you wish to replace a reference to one object with a reference to another object.

Categories

Resources