-3

Code:

objectType request = factory.create<objectType>();

public class factory
{
    public static T create<T>() where T : new()
    {
      T obj = new T();
      PropertyInfo propertyInfo = obj.GetType().GetProperty("client_no");
      propertyInfo.SetValue(obj, CLIENT_NUMBER, null);
      return (T)Convert.ChangeType(obj, typeof(T));
     }
}

Explanation:

I am creating a generic factory fn() that sets 2 object properties.

These properties are consistent throughout all the objects I am wanting to initialize.

1) How I call my function

objectType request = factory.create<objectType>(); // <-- This works

1b) From here if I wanted, I could do the following, but is extra code that is repetitive throughout all my objects

request.client_no = CLIENT_NUMBER;

2) Below is my factory fn()

public static T create<T>() where T : new()
{
  T obj = new T();      

  // Here is where I am having trouble setting client_no I will explain in #3         

  return (T)Convert.ChangeType(obj, typeof(T)); // <-- This works returns generic type
}

3) I have tried PropertyInfo to set the object properties as follows

PropertyInfo propertyInfo = obj.GetType().GetProperty("client_no");
propertyInfo.SetValue(obj, CLIENT_NUMBER, null);

I have also tried this

obj.GetType().GetProperty("client_no").SetValue(obj, CLIENT_NUMBER, null); 

And I have tried

T obj = new T();      
var t = typeof(T);
var prop = t.GetProperty("client_no");
prop.SetValue(obj, CLIENT_NUMBER);

4) Here is the error that I am receiving

Object reference not set to an instance of an object

More/Newer information:

So with further research. The 3rd party objects properties do not have getters and setters {get; set;} which is why the GetType() & SetValue() do not work.

My co-worker pointed out that the property is a single assignment which is why we can do

request.client_no = CLIENT_NUMBER;

So my question is how do I set these properties?

13
  • 5
    It's really not clear what your updateAccountData method is meant to achieve. You can't dynamically create variables in C#... if you tell us more about what you're actually trying to achieve, we can help you more. Commented Feb 26, 2015 at 17:51
  • So does your class objectName have the properties you are trying to populate? Or is the idea that those properties don't exist? What do you ultimately expect to do with request? Commented Feb 26, 2015 at 17:55
  • @MattBurland They will have it or I can add an option to test if they exist before I add the items. Commented Feb 26, 2015 at 17:57
  • 2
    @Demodave It's not easily understood. We're all guessing about what you're trying to do. Commented Feb 26, 2015 at 18:03
  • 1
    @Demodave I don't know what you're trying to achieve here but if you think you need to dynamically create new properties on objects then the angle you are coming at it from is wrong. See: XY Problem Commented Feb 26, 2015 at 18:05

3 Answers 3

2
+100

Using reflection, you can do something like this:

public objectName updateAccountData(int accountId, Dictionary<string,string> accountData)
{
    var request = new objectName();
    var t = typeof(objectName);
    foreach (var k in accountData)
    {
        var prop = t.GetProperty(k.Key);   // you might want to check property exists before trying to set it
        prop.SetValue(request,k.Value);
    }
    return request;
}

This assumes that your objectName class already has all the properties you need to populate.

Note that reflection is slower than directly accessing a property, so if this code is in a performance critical section of your application, it might be a problem (profile it). A couple of obvious optimization could be applied pretty easily. For example, you could store all the PropertyInfo objects retrieved from GetProperty in a Dictionary<string,PropertyInfo> to avoid having to keep looking them up. More complicated, you can actually use expression trees to build and compile expressions for property access.

For a field just substitiute t.GetField(k.Key) for GetProperty.

If you don't know if it's a field or a property (or have a mix of both), then you could use GetMember and then examine the MemberType to decide.

Sign up to request clarification or add additional context in comments.

13 Comments

This seems like it has potential. It looks like another problem I had solved with research something similar to PropertyInfo propertyInfo = obj.GetType().GetProperty(key); propertyInfo.SetValue(obj, value, null);
Don't worry about the performance of this code. You said this is a 3rd party API object, filling in the object via reflection will be orders of magnitude faster than the actual call to the 3rd party API so it will never be your bottleneck. I know Matt only mentioned it for completeness, but notice he also said profile it. If you ever do have a performance problem, profile first then optimize the true problem area.
Reflection is what the code in the answer uses to find the properties on the object at runtime. Profiling is the act of running a profiler against your running program to find out where any bottlenecks are. You can only know if profiling is needed if you have a specified performance goal. If you don't have any performance goals or if the program is meeting those goals, don't spend time worrying about performance or profiling.
@Demodave: Where? Likely GetProperty is returning null. As my comment said, you should check that the property actually exists. This can be as simple as if (prop != null) before you try prop.SetValue. What you should do if prop == null is up to you.
@Demodave: So is it not a property then? Is it a field? In that case use GetField instead of GetProperty. And then you should be able to SetValue on the FieldInfo returned by GetField.
|
2

I see the accepted answer but, here is another way which doesn't involve calling reflection directly and instead uses DLR.

  public static T create<T>() where T : new()
  {
     T obj = new T();
     ((dynamic)obj).client_no = CLIENT_NUMBER;
     return obj;
  }

MSDN Dynamic Language Runtime Overview

The essential part here is that instead of writing the reflection calls yourself the compiler will take care of it. The link above discusses the benefits of using this over making reflection call directly.

2 Comments

While this answer is probably correct and useful, it is preferred if you include some explanation along with it to explain how it helps to solve the problem. This becomes especially useful in the future, if there is a change (possibly unrelated) that causes it to stop working and users need to understand how it once worked.
I updated the answer with links to the MSDN DLR documentation.
1

SOLVED. Here's how.

My main issue was a miss-understanding, The item I was trying to set was not a property, but rather a field.

To better understand the difference yourself you can check out this.

Here is how I fixed it:

I set the field types of the generic

public static T create<T>() where T : new()
{
  T obj = new T();

  Type myType = typeof(T);
  FieldInfo myFieldInfo = myType.GetField("client_no");
  myFieldInfo.SetValue(obj, CLIENT_NUMBER);                        

  return obj;
}

Special thanks to @MattBurland which led me in the right direction.

2 Comments

Not sure what you think Convert.ChangeType is doing for you. obj is already declared as type T, so you should be able to just return it.
@MattBurland, That's true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.