3

The problem i am trying to solve is that i want all properties for a given class to escape invalid characters depending on whether a given attribute has been applied.

Take following class:

public class MyClass
{
    [EscapeInvalid]
    public string Prop1 {get; set;}

    public string Prop2 {get; set;}
}

Here is my defined attribute class

public class EscapeInvalidAttribute : Attribute 
{
    string escapedValue;
    public string EscapedValue
    {
        get
        {
            return escapedValue;
        }
        set
        {
            escapedValue= Escape(value);
        }
    } 
}

In a nutshell if the property for a given class has the [EscapeInvalid] applied i want to have the setter escape the value.

Is this possible?

I understand that i can just update each setter to apply the escape but was looking for a cleaner way to do this. Thanks in advance for any guidance.

8
  • Are you okay with using a class instead of String? For a cleaner way of doing things, I think that's the way I'd go. You can overrdide / extend your class to make it do other things string does if needed. Commented Dec 11, 2019 at 17:30
  • @Nikki9696 are you referring to a class inside the attribute definition? Commented Dec 11, 2019 at 17:32
  • No, you'd have a custom class, like MyEscapedString, and use that for your property instead of "string" Commented Dec 11, 2019 at 17:33
  • Because I don't think you can use attributes for this. I could be wrong of course. =) Commented Dec 11, 2019 at 17:34
  • No i can't do that because this class is a request that is sent off to api and needs to not change Commented Dec 11, 2019 at 17:34

2 Answers 2

2

Attributes are supported in C# for supplying run time information. It doesn't have pre processor like other Attribute Based programming languages that can change the behavior of data type at runtime.

There is a hard way to do it by creating an IL injector to support this behavior, but that's not very popular in .Net world and requires a lot of plumbing code to achieve it.

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

2 Comments

Thanks for feedback. Ya i wasn't sure if this was possible. It's not the end of the world for me to just update setters to apply the escape where applicable.
Just wondering why a downvote here? would be nice to provide reasoning for this.
0

If you are open to making your properties virtual, you can use Castle DynamicProxy to intercept calls to setters and change the values as you please. A huge advantage of this method would be - you are relying on a industry proven library that has heaps of support and maintenance. One obvious disadvantage - introducing a layer over all your method invocations will impact performance (must be noted, NHibernate and EF Core seem to not have issues with that)

public class Hook : IProxyGenerationHook
{
    public void MethodsInspected()
    {
        // again, we probably won't use it here
    }

    public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
    {
        // we assume everything is correctly marked `virtual` and do nothing here
    }

    public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
    {
        // you of course can go way fancier than that. 
        // one thing of note here is that your Property setters would be prefixed with "set_", but nothing stops you from targeting other methods as well
        var prop = type.GetProperties()
        .FirstOrDefault(p => methodInfo.Name == $"set_{p.Name}" && p.GetCustomAttribute(typeof(EscapeInvalidAttribute)) != null);
        return prop != null;
    }
}
public class EscapeInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {        
        invocation.Arguments[0] = EscapeInvalidAttribute.Escape((string)invocation.Arguments[0]);
        invocation.Proceed(); // allow the call to proceed anyway       
    }
}
public class EscapeInvalidAttribute : Attribute
{
    public static string Escape(string input)
    {
        return $"escape|{input}|string";
    }
}
public class MyClass
{
    [EscapeInvalid]
    public virtual string Prop1 { get; set; }

    public virtual string Prop2 { get; set; }

}
void Main()
{
    var generator = new ProxyGenerator();
    var options = new ProxyGenerationOptions
    {
        Hook  = new Hook()
    };
    MyClass myClassProxy = (MyClass)generator.CreateClassProxy(typeof(MyClass), options, new[] {new EscapeInterceptor()});
    myClassProxy.Prop1 = "test";
    myClassProxy.Prop2 = "test";
    Console.WriteLine(myClassProxy.Prop1);
    Console.WriteLine(myClassProxy.Prop2);
}

UPD added more canonical implementation using a IProxyGenerationHook

1 Comment

Ideally, shouldn't you use a ProxyGenerationHook class to filter at proxy creation time the methods to proxy?

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.