Reflection. What can we achieve using it?

2020-02-03 06:47发布

I'm reading and learning about reflection in C#. It would be fine to know how can it help me in my daily work, so I want people with more experience than me tell me samples or ideas about what kinds of things can we achieve using it, or how can we reduce de amount of code that we write.

Thanks.

14条回答
Bombasti
2楼-- · 2020-02-03 07:16

The properties window in VS is reflection based - if you make a user control you can modify any properties on it from the PropertyGrid (its also a control you can use if you want) instantly. Of course you can add attributes to enhance how it is displayed (which are accessed via reflection).

I've also used it to implement a custom binary serialization class.

Here I have a class where I use reflection to serialize / de-serialize it - and provide attributes for additional UI information.

[TypeConverter(typeof(IndexedExpandableObjectConverter))]
[BinarySerializeable]
public sealed class Socket
{
    #region Fields (7) 

    [SerializedPosition(0)]
    Byte _mode = 1;

    ...

    [SerializedPositionAttribute(4)]
    UInt16 _localPort;

    ...

#region Properties (5) 

    [DisplayName("Listning Port")]
    [Description("The port which the socket will listen for connections on")]
    [DisplayIndex (0)]
    public UInt16 LocalPort
    {
        get { return _localPort; }
        set { _localPort = value; }
    }

    ...

And serialization function - as you can see, it just takes an object and the byte order (endianness) you want. Everything else is determined by reflection. The default SerializationProvider works using SerializedPosition attributes on fields within the object (private or not).

public static Byte[] Serialize(Object obj, ByteOrder streamOrder)
{

    var provider = GetProvider(obj);

    if (provider.CanSerialize(obj.GetType()))
        return provider.Serialize(obj, streamOrder);

    throw new ArgumentException(obj.GetType() + " is non-serialisable by the specified provider '" + provider.GetType().FullName + "'.");
}


private static IBinarySerializatoinProvider GetProvider(Object obj)
{

    var providerAttrib = Reflector.GetAttribute<BinarySerializationProviderAttribute>(obj);

    if (providerAttrib != null)
        return CreateProvider(providerAttrib.ProviderType);

    return CreateProvider(typeof(SerializationProvider));
}
查看更多
冷血范
3楼-- · 2020-02-03 07:17

Reflections are nice for "late binding" solutions where you do not want to have a physical reference connected to your project but rather "connect" it later on. That way if the reference is not there and it is not critical, you get no unhandlish errors of missing references. You get a controlled error that you can handle.

查看更多
闹够了就滚
4楼-- · 2020-02-03 07:18

I've only used reflection in production code once. It was a situation where I had to make adjustments to what - up to that point in time - had been standardised usage of a particular class method in a startup routine (sorry not to be more specfic - it was a while ago and the details are hazy). The only way round the problem was to introduce a different version of the method and examine various criteria/code conditions etc. at runtime to determine which method I should be calling. It was a pretty compact piece of code that provided a succint solution to what would otherwise have been a messy problem to solve.

查看更多
够拽才男人
5楼-- · 2020-02-03 07:19

I use it for:

  • Dependency injection
  • Workarounds for Microsofts lack of motivation to add things like "covariant / contravariant generic" and "new() constraints with parameters"
  • Aspect oriented programming (to some extent, mostly I use PostSharp)
查看更多
Juvenile、少年°
6楼-- · 2020-02-03 07:23

It is invaluable for library code that doesn't have any need to know about the caller - like with generics, but richer access to the data. Examples:

  • ORMs (materialization etc)
  • serialization / deserialization
  • object cloning / deep copy
  • UI / binding code (strictly this is ComponentModel, but you can mix the two - for example, HyperDescriptor)

You should of course try to minimise the amount of reflection you do, but you can mitigate the cost by caching delegates from Delegate.CreateDelegate / Expression / DynamicMethod

查看更多
smile是对你的礼貌
7楼-- · 2020-02-03 07:26

This is way to execute methods based on a enum or a magic string...


    public enum ReflectionTestMethods
    {
        MethodA,
        MethodB,
        MethodC
    }
    public class ReflectionTest
    {

        public void Execute(ReflectionTestMethods method)
        {
            MethodInfo methodInfo = GetType().GetMethod(method.ToString()
                , BindingFlags.Instance | BindingFlags.NonPublic);
            if (methodInfo == null) throw new NotImplementedException(method.ToString());
            methodInfo.Invoke(this, null);
        }

        private void MethodA()
        {
            Debug.Print("MethodA");
        }

        private void MethodB()
        {
            Debug.Print("MethodB");
        }

        private void MethodC()
        {
            Debug.Print("MethodC");
        }
    }

But this is maybe a better solution...


    public class ActionTest
    {
        private readonly Dictionary _actions = new Dictionary();

        public ActionTest()
        {
            _actions.Add(ReflectionTestMethods.MethodA.ToString(), new Action(MethodA));
            _actions.Add(ReflectionTestMethods.MethodB.ToString(), new Action(MethodB));
            _actions.Add(ReflectionTestMethods.MethodC.ToString(), new Action(MethodC));
        }

        public void Execute(ReflectionTestMethods method)
        {
            if (!_actions.ContainsKey(method.ToString())) 
                throw new NotImplementedException(method.ToString());
            _actions[method.ToString()]();
        }

        private void MethodA()
        {
            Debug.Print("MethodA");
        }

        private void MethodB()
        {
            Debug.Print("MethodB");
        }
        private void MethodC()
        {
            Debug.Print("MethodC");
        }
    }
查看更多
登录 后发表回答