As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/
Options

C# - Reflection & ReflectionPermission

DortmunderDortmunder Registered User regular
edited October 2010 in Help / Advice Forum
Working in a C# assembly, I have 2 classes, both in the same namespace: ValidEntity and ValidEntityFactory.

ValidEntity is an abstract class that is extended by several others. ValidEntityFactory is used to load ValidEntities from the database.

Here is a snapshot of ValidEntity (I've removed irrelevant methods & properties)
public abstract class ValidEntity
  {
    public string Code { get; private set; }
  }

The ValidEntityFactory is trying to get a handle on the Code set method like so:
Type entityType = typeof(T); // T is one of the classes that extends ValidEntity

BindingFlags setPropertyBindingFlags = BindingFlags.ExactBinding | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;

PropertyInfo codeSetProperty = GetPrivateProperty(entityType, "Code", setPropertyBindingFlags, typeof(string));

// ...

    private static PropertyInfo GetPrivateProperty(Type t, string propertyName, BindingFlags bindingFlags, Type returnType)
    {
      PropertyInfo pi = null;
      
      while ((pi == null) && (t != typeof(object)))
      {
        pi = t.GetProperty(propertyName, bindingFlags, null, returnType, Type.EmptyTypes, null);
        t = t.BaseType;
      }

      return pi;
    }

However it seems unable to get the PropertyInfo for a private property (returns null).

I did some research and saw somewhere that you need to allow "reflection permission" on the method you want if it is private, but I couldn't find any real examples on the net.

Here is what I've been fiddling with, in ValidEntity.cs:
using System.Security.Permissions;

namespace Business.ValidEntities.Base
{
  [ReflectionPermission(SecurityAction.Assert, MemberAccess = true)]
  public abstract class ValidEntity

// ...

I've also tried placing that attribute on the set method like so:
public string Code { get; [ReflectionPermission(SecurityAction.Assert, MemberAccess = true)]private set; }

But still no luck. Am I doing something wrong? Am I on the right track?

steam_sig.png
Dortmunder on

Posts

  • Options
    TejsTejs Registered User regular
    edited October 2010
    Let me make sure I understand this problem:

    You have a class A, with a public get / private set property named PROP. You have another class B, which is trying to return an C from a method with PROP set to some value, where C derives A.

    However, you are finding it very hard to set PROP from the factory method. Correct?

    Edit: Also, A look like a class you created... If so, you can easily solve this by marking the property as protected set.
        public class BaseClass
        {
            public string Code { get; protected set; }
        }
    
        public class DerivedClass : BaseClass
        {
            public void SetCode(string value)
            {
                Code = value;
            }
        }
    
        public class BaseClassFactory
        {
            public BaseClass GetBaseClassInstance()
            {
                DerivedClass x = new DerivedClass();
    
                x.SetCode("Hello World");
    
                return x;
            }
        }
    

    Tejs on
  • Options
    GanluanGanluan Registered User regular
    edited October 2010
    Tejs is right, and it would make a lot more sense to make this a protected set if possible. If for some reason you can't, you can definitely access a private property using Reflection.

    Try calling it like this instead of the overloaded call you are using:
    PropertyInfo pi = obj.GetType().GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    

    Ganluan on
  • Options
    DortmunderDortmunder Registered User regular
    edited October 2010
    Yeah actually the GetPrivateProperty() method I wrote does call GetProperty() on the type, it just walks up the base types as well.

    For now I've switched it to protected set to get it working so I can work on something else and I'm going to speak with our architect on Monday when he gets back.

    The reason we want it private is that we don't want the derived types to be able to modify the Code property, only the factory.

    Thanks guys

    Dortmunder on
    steam_sig.png
  • Options
    TejsTejs Registered User regular
    edited October 2010
    In that case, why not make it a readonly property?
        public class BaseClass
        {
            public readonly string Code { get; protected set; }
        }
    
        public class DerivedClass : BaseClass
        {
            public DerivedClass(string value)
                : base()
            {
                Code = value;
            }
        }
    
        public class BaseClassFactory
        {
            public BaseClass GetBaseClassInstance()
            {
                DerivedClass x = new DerivedClass("Hello World");
    
                return x;
            }
        }
    

    Then, you can return the DerivedClass from the factory method and it has no method to set the code value.

    Edit: You don't actually have to make it a readonly property, you just need to set it as part of the constructor. The readonly is just for code clarity.

    Tejs on
  • Options
    GanluanGanluan Registered User regular
    edited October 2010
    Glad you got it sorted Dort - I knew you were calling the GetProperty method, but you were calling an overloaded version with different binding flags. If you call it like I showed, you should be able to access it without a problem.

    In your case though, Tejs' solution is much cleaner. It's not often you get a good chance to use readonly either :P

    Ganluan on
Sign In or Register to comment.