1

I have this generic method:

public Guid Save<T>(T obj)
    {
        Guid newId = Guid.NewGuid();
        try
        {
            foreach (MethodInfo method in (typeof(T)).GetMethods())
            {
                if (IsXmlElement(method))
                {
                    // A way to get this method's value
                    // e.g. if T has method GetName, and GetName was assigned 'John' 
                    //i.e. object.GetName = 'John'Is there a way to get 'John' from this GetName method?
                }
            }

Then, I have an object, myObject.Name = 'John'... and myObject was passed to save method thus: Save(myObject); Is there any way I can get the value 'John' inside the Save method?

Any suggestion would be appreciated. Thanks.

osagie
  • 251
  • 2
  • 6
  • 15
  • 1
    What is IsXmlElement? Why do you say that GetName is a method and use it like a property? `object.GetName = 'John'` Also, value can be assigned to a filed or a property, in case of method it is likely a result of calculation, and it could also require parameters. Where will you take those parameters from? – ironstone13 Jan 12 '17 at 20:03
  • That is just a method to check if that method has a particular attribute... - though that is not necessary for this question – osagie Jan 12 '17 at 20:05
  • Please refer to this question http://stackoverflow.com/questions/232535/how-do-i-use-reflection-to-call-a-generic-method – ironstone13 Jan 12 '17 at 20:06
  • Are you interested in how to invoke any generic method, or how to restrict your generic types to those that have a specific method? – ironstone13 Jan 12 '17 at 20:11

5 Answers5

2

If you want to iterate through the properties (I assume you mean properties when you say "methods" from your example) based on the generic type, you can use the TypeDescriptor class:

public Guid Save<T>(T obj)
{
    Guid newId = Guid.NewGuid();
    try
    {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(typeof(T)))
        {
            if (IsXmlElement(method))
            {
                object value = property.GetValue(obj);
                // ...
            }
        }

If you always infer the type (i.e. T is always the type of obj and not a base type or interface), you don't need generics at all:

public Guid Save(object obj)
{
    Guid newId = Guid.NewGuid();
    try
    {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(obj))
        {
            if (IsXmlElement(method))
            {
                object value = property.GetValue(obj);
                // ...
            }
        }

You might want to also check out the XmlSerializer class. It seems that you are creating an XML from your source object manually. XmlSerializer probably has already everything you need with less work.

Sefe
  • 13,731
  • 5
  • 42
  • 55
1

If possible, I would enforce an requirement that any type passed to your generic method is derived from a common interface. Then you can reference any of the properties that are defined in that interface (in this case name). Your method definition would look something like this:

 public Guid Save<T>(T obj) where T : iSaveable
 { 
    ...

where iSaveable would be the name of the interface you created.

Abe Miessler
  • 82,532
  • 99
  • 305
  • 486
  • enforcing requirement won't resolve my issue. This is because properties I would want to get values for a not specific/fixed. These are propeties of classes that has certain attribute. A new class could be added, with custom properties, but if any of those properties contain this attribute, it would qualify for value retrieval – osagie Jan 12 '17 at 21:38
1

It really sounds like you are looking to work with properties rather than methods in this example. In the case of properties you would write something like this:

void Main()
{
    var obj = new TestObject();
    foreach (var prop in obj.GetType().GetProperties())
    {
        Console.WriteLine("{0} = '{1}'", prop.Name, prop.GetValue(obj));
    }
}

class TestObject
{
    public TestObject()
    {
        FirstName = "John";
        LastName = "Hancock";
    }

    public string FirstName { get; }
    public string LastName { get; }
}

You could also use this to get the values of fields instead of properties by changing the GetProperties call to GetFields. This will only work with public fields or properties though. If you wanted to wanted to save non-public fields or properties you would need to add BindingFlags to the GetProperties/GetFields call:

void Main()
{
    var obj = new TestObject();
    foreach (var prop in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
    {
        Console.WriteLine("{0} = '{1}'", prop.Name, prop.GetValue(obj));
    }
}

class TestObject
{
    private readonly string _firstName;
    private readonly string _lastName;

    public TestObject()
    {
        _firstName = "John";
        _lastName = "Hancock";
    }
}
Trey Tomes
  • 76
  • 9
  • Thanks for you contribution @Trey Tomes. My mistake actually, I was actually looking to work with properties. I posted the question before realizing this – osagie Jan 12 '17 at 21:34
  • That's no problem @osagie. I'm happy to have interpreted your question correctly. – Trey Tomes Jan 13 '17 at 14:54
0

You could cast the object to the known type then access the Name property. Because you don't show us your classes, let's pretend your object is of type Person, then inside Save:

if (obj is Person)
{
    string name = ((Person)obj).Name;
} 
else
{ ... }

More info about is here.

Quantic
  • 1,779
  • 19
  • 30
0

You can if you put a constraint on the type parameter like this:

public Guid Save<T>(T obj) where T : ISomeInterface
    {
        Guid newId = Guid.NewGuid();
        try
        {
            foreach (MethodInfo method in (typeof(T)).GetMethods())
            {
                if (IsXmlElement(method))
                {
                    // A way to get this method's value
                    // e.g. if T has method GetName, and GetName was assigned 'John' 
                    //i.e. object.GetName = 'John'Is there a way to get 'John' from this GetName method?
                }
            }

and where your myObject implements the ISomeInterface interface.

Hope that helps

MichaelDotKnox
  • 1,312
  • 1
  • 14
  • 17