software_writer_nyc

PRIMARY QUESTION

Can one get a unique id from a method name in the C# language

.....................................................................................

the method name is the name that can be passed to a c# delegate

(for this thread .. lets agree a method name is NOT a literal string wiht quotes such as "my_interesting_method")

How flexible is a delegate in terms of system reflection

Perhaps the unique id would be a string, perhaps an intergral type (int);

I am not trying to go from a string representation to method invocation .. at least unless I am forced to.

elided example (not compilable)

public class z2000

{

public static in method_sort_by_id() {};

public static string desired_experience()

{

string x = method_name_from_method(method_sort_by_id);

//above line is the first step in ideal experience .. improvements abound

//shortcoming .. not internationalized ... if the info was shown to users

return x;

}

public void actual_experience()

{

int primary_key = 222;//unique id as in relation db;

store_delegate_with_names(method_sort_by_id, "method_sort_by_id", "typical method to sort by id", primary_key");

//above line is moderately acceptable

}

}//end of class

Some Thoughts

Please correct me if I am wrong on some of these thoughts if necessary.

1. It seems that one can only pass method names to delegate constuction and no other c# constuction. (I am not referring to passing a string).

2. It seems that delegates can not be compared meaningfully.

3. It seems that the type info on the delegate returns the signature of the delegate in some form, which does not reveal the method name

4. It seems one can only invoke the method (or methods for invocation list) and not much deep reflection.

5. It seems that refection goes from string names to invocation .. and not vice versa

------------------------------------------------------------------------------

Any thoughts I hope this question is useful to someone else as well.

Thanks in advance.



Re: Visual C# General C# Delegate Method Reflection Capabilities

TaylorMichaelL

Quite a few questions here. I think, though, that you are mixing terminology and so the questions you're asking don't line up. A delegate is nothing but a function signature, a type. Events are objects that have a delegate as a type. However delegates can be used in other places as well. You can use delegates as properties, fields and parameters to methods. The Delegate (or more correctly the MulticastDelegate) class is used to manage lists of functions. Ultimately when you define a delegate in code an instance of the MulticastDelegate class is used to maintain the list of function(s) to invoke. Each method added to the delegate is effectively wrapped in an instance of the Delegate class. Other than the fact that this class can not be directly instantiated it is no different then any other class. It exposes methods to add and remove delegates from the list it maintains. When told it executes each delegate in the list.

  1. You can use any object that has a function signature that matches the delegate signature with a delegate. In theory only methods meet this requirement although it might be possible, not that you would, to use a property getter or setter. How you actually get the object to pass to the delegate is up to you (reflection, name, whatever).
  2. Delegates themselves, no. Since they are types it would be like comparing types. Each language defines its own rules for type equality but most languages say that two types are different if they have different names even if they are structurally equivalent. Thus class A and class B are different types even if they both contain a single string field.

    MulticastDelegate instances can be compared although it'll properly rarely be meaningful. Since they are reference types they compare as references. So if you assigned an event name to two different local variables then the local variables would be equal. However if you had two different events and compared them (assuming that they were of the same type and had the same invocation list) they would still be different.

    Delegate instances can also be compared. In this case the method information is represented by a reference type (which happens to be cached) so you can expect that if two instances refer to the same method of a type (but not necessarily the same instance) then the method references will match. The Target property will point to the owning instance (or null). It will also use reference type semantics so provided both instances are the same comparison should work.
  3. Again, a delegate is a type and not a list of methods to invoke. If you request the type information of a delegate you will get the delegate type information. You'd get information about its parameters and return type and that would be it. Delegates do not have associated methods.

    If you get the type information from a MulticastDelegate instance then you'd get back the type information. You could then use the GetInvocationList method to retrieve the list of Delegate instances associated with it.

    The Delegate instances would each contain properties to identify the type and method to invoke and the optional target instance to invoke it on. Reference equality is used here so two Delegate instances would be equal if they pointed to the same type.method and they both referred to the same instance. Note however that if you simply used the Delegate instances themselves in a comparison (say Equals or ==) then it wouldn't work because they are reference types. You would have to compare the individual properties.
  4. On a delegate type you get the function signature and return type.

    On a MulticastDelegate you can get the associated delegate type and the list of Delegate instances associated with it.

    On a Delegate instance you can get the method to invoke and the optional target instance.
  5. Reflection is generally used to go from string names to runtime type information but it can do so much more. You can use reflection to analyze a class hierarchy, get all available operations on an object, determine the features available on an object and so much more. For example without ever using a string you can determine if an arbitrary object supports collection semantics and therefore treat the object as a collection.

IMHO

Michael Taylor - 4/10/07

http://p3net.mvps.org





Re: Visual C# General C# Delegate Method Reflection Capabilities

software_writer_nyc

I suppose an interfaces may have some of the properties that are desired here.



Re: Visual C# General C# Delegate Method Reflection Capabilities

software_writer_nyc

PREAMBLE
Thank You for such a quick and comprehensive response.
My <thoughts> were just specifics for my problem .. I could have stated that
The <thoughts> were not intended to be exhaustive explanations.
CORE
The documentation for C# for delegate writes (elided)
Delegate.Method Property
Property Value
A MethodInfo describing the method represented by the delegate
(note the capital M)

So it may be easy to confuse in this note the notions of
general <method> ... and Delegate.Method Property
I will assume at some point in your response you meant
Delegate.Method Property or sibling methods
Thanks for inspiring me to examine those methods/properties more closely.

PRIMARY QUESTION (repeat)
Can one get a unique id from a method name in the C# language
ANSWER
Substantially yes or very usefully close
once a delegate is created with the method then
one can get the method name and much more with <Delegate.Method Property >

SAMPLE C#
sb.Append(" Reflection");
System.Reflection.MethodInfo mi_q = cp.comparison_imp.Method;
sb.Append("[");
sb.Append(mi_q.Module.Name);
sb.Append("]");
sb.Append(mi_q.DeclaringType.Name);
sb.Append(".");
sb.Append(mi_q.Name);
sb.Append(" Target ");
sb.Append((null == cp.comparison_imp.Target) "None" : cp.comparison_imp.Target.ToString());

TEXT excerpt copied from text visualizer in VS2005
"Reflection[discrete.exe]person_sequence.comparison_birth_date Target None"

THANKS


...............................
SOME SECONDARY NOTES

The keyword ... event ... is <NOT> used directly in the body of software about which I am writing. Moderately interesting is that keyword .. delegate .. is not in the software I wrote. I am simply using the delegate declared in the
System namespace .. Comparison<T>.

The software is functioning correctly and simply does a multifield sort on some data. The methods are encapsulated by delegate only (no event). The particular methods to be used are dynamically selected.
This is a software sample

public class cda<T> //generic
{
//elided explanatory not necessarily ready for compiler
public Comparison<T> comparison_imp;//Systems Namespace ..Generic delegate
public string name_imp;//used to produce a humanly readable audit trail
}
//a list of these are used subsequently
public List<cda<person_c>> cs = new List<cda<person_c>>();
list_q.Sort(csq.compare_sequence);






Re: Visual C# General C# Delegate Method Reflection Capabilities

TaylorMichaelL

A method implementation can be uniquely identified by the method's FullName combined with the method's DeclaringType.FullName. This is guaranteed unique across the board in all cases except generics. For generics it will be uniquely only as much as the generic types are specified. Interfaces are not method implementations so they are skipped.

Combining the Target property of Delegate in combination with the Method property will uniquely identify an instance method provided the target is not a value type. If it is then equality is sort of meaningless I believe.

Michael Taylor - 4/10/07

http://p3net.mvps.org





Re: Visual C# General C# Delegate Method Reflection Capabilities

software_writer_nyc

you wrote

>>>>>>>>>>>>>>method's FullName

I do not understand what you meant by that phrase when applied to our discussion.

is that a notion, a method of some class, unintentional, or other

Perhaps a C# example would help.

Again we may have the misunderstanding possiblity between senses of method ...

general method .. vs (Delegate.Method property)

Thanks





Re: Visual C# General C# Delegate Method Reflection Capabilities

TaylorMichaelL

A little of both. There is no FullName property on MethodInfo but Name is not enough because of overloading. The ToString method returns everything you need but I'm generally hesitant to rely on its return value for any critical code because it could change. Nevertheless the Name in combination with the parameters of a method make it unique within the parent type. So if I wanted to uniquely identify a method I would do so like this.

Code Snippet

static public string GetUniqueMethodName ( MethodInfo method )

{

return method.ToString() + "[" + method.DeclaringType.FullName + "]";

}

I think the above method works even for generic methods but I haven't tested it. The resulting string is really long due to all the names that have to be taken into account but it'll be unique within the appdomain at least.

An alternative would be to get the method's MetadataToken property which is unique within its owning module. This in combination with a module's unique identifier can be used as well for uniquely identifying a method. For a module you could use the ModuleVersionId or perhaps even the MetadataToken. What I'm not sure about is whether this can change across compilations of the underlying assembly. So, for example, I'm not sure if you compiled an assembly containing class A yesterday whether it would have the same token today after you recompiled it again. You'd have to test that and see. However if they are consistent then this would be a faster/smaller way to uniquely identify the types.

Michael Taylor - 4/12/07





Re: Visual C# General C# Delegate Method Reflection Capabilities

software_writer_nyc

I suppose the return type and method signature could be composed

piecemeal (sequence of methods) in the way

System.Reflection.MethodInfo.ToString()

does ...... if more content guarantees are desired.

I may post such a sample in this thread in the near future.

For my small amount of testing .. the string length is accesptable to me, as a safeguard against overloading.

Thanks