Is it possible to have a delegate as the parameter of an attribute?
Like this:
public delegate IPropertySet ConnectionPropertiesDelegate();
public static class TestDelegate
{
public static IPropertySet GetConnection()
{
return new PropertySetClass();
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,AllowMultiple=false,Inherited=true)]
public class WorkspaceAttribute : Attribute
{
public ConnectionPropertiesDelegate ConnectionDelegate { get; set; }
public WorkspaceAttribute(ConnectionPropertiesDelegate connectionDelegate)
{
ConnectionDelegate = connectionDelegate;
}
}
[Workspace(TestDelegate.GetConnection)]
public class Test
{
}
And if its not possible, what are the sensible alternatives?
No, you cannot have a delegate as an attribute constructor parameter. See available types: Attribute parameter types
As a workaround (although it's hacky and error prone) you can create a delegate with reflection:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class WorkspaceAttribute : Attribute
{
public ConnectionPropertiesDelegate ConnectionDelegate { get; set; }
public WorkspaceAttribute(Type delegateType, string delegateName)
{
ConnectionDelegate = (ConnectionPropertiesDelegate)Delegate.CreateDelegate(typeof(ConnectionPropertiesDelegate), delegateType, delegateName);
}
}
[Workspace(typeof(TestDelegate), "GetConnection")]
public class Test
{
}
Other possible workaround is creating abstract base Attribute type with abstract method matching your delegate definition, and then implementing the method in concrete Attribute class.
It has following benefits:
Annotation is more concise and clean (DSL like)
No reflection
Easy to reuse
Example:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple=false, Inherited=true)]
public abstract class GetConnectionAttribute : Attribute
{
public abstract IPropertySet GetConnection();
}
public class GetConnectionFromPropertySetAttribute : GetConnectionAttribute
{
public override IPropertySet GetConnection()
{
return new PropertySetClass();
}
}
[GetConnectionFromPropertySet]
public class Test
{
}
I solved this by using an enum and a mapping array of delegates. Although I really like the idea of using inheritance, in my scenario that would require me to write several child classes to do relatively simple stuff. This should be refactorable as well. The only drawback is that you have to make sure to make the delegate's index in the array corresponds to the enum value.
public delegate string FormatterFunc(string val);
public enum Formatter
{
None,
PhoneNumberFormatter
}
public static readonly FormatterFunc[] FormatterMappings = { null, PhoneNumberFormatter };
public string SomeFunction(string zzz)
{
//The property in the attribute is named CustomFormatter
return FormatterMappings[(int)YourAttributeHere.CustomFormatter](zzz);
}
Necromancing.
Augmented on the accepted answer to use a dynamic delegate type:
namespace NetStandardReporting
{
// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class DynamicDllImportAttribute
: System.Attribute
{
protected string m_name;
public string Name
{
get
{
return this.m_name;
}
}
public DynamicDllImportAttribute(string name)
: base()
{
this.m_name = name;
}
private static System.Type CreateDelegateType(System.Reflection.MethodInfo methodInfo)
{
System.Func<System.Type[], System.Type> getType;
bool isAction = methodInfo.ReturnType.Equals((typeof(void)));
System.Reflection.ParameterInfo[] pis = methodInfo.GetParameters();
System.Type[] types = new System.Type[pis.Length + (isAction ? 0: 1)];
for (int i = 0; i < pis.Length; ++i)
{
types[i] = pis[i].ParameterType;
}
if (isAction)
{
getType = System.Linq.Expressions.Expression.GetActionType;
}
else
{
getType = System.Linq.Expressions.Expression.GetFuncType;
types[pis.Length] = methodInfo.ReturnType;
}
return getType(types);
}
private static System.Delegate CreateDelegate(System.Reflection.MethodInfo methodInfo, object target)
{
System.Type tDelegate = CreateDelegateType(methodInfo);
if(target != null)
return System.Delegate.CreateDelegate(tDelegate, target, methodInfo.Name);
return System.Delegate.CreateDelegate(tDelegate, methodInfo);
}
// protected delegate string getName_t();
public DynamicDllImportAttribute(System.Type classType, string delegateName)
: base()
{
System.Reflection.MethodInfo mi = classType.GetMethod(delegateName,
System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
);
// getName_t getName = (getName_t)System.Delegate.CreateDelegate(delegateType, mi));
System.Delegate getName = CreateDelegate(mi, null);
object name = getName.DynamicInvoke(null);
this.m_name = System.Convert.ToString(name);
}
} // End Class DynamicDllImportAttribute
public class DynamicDllImportTest
{
private static string GetFreetypeName()
{
if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
return "libfreetype.so.6";
return "freetype6.dll";
}
// [DynamicDllImportAttribute("freetype6")]
[DynamicDllImportAttribute(typeof(DynamicDllImportTest), "GetFreetypeName")]
public static string bar()
{
return "foobar";
}
// NetStandardReporting.DynamicDllImportTest.Test();
public static void Test()
{
System.Reflection.MethodInfo mi = typeof(DynamicDllImportTest).GetMethod("bar",
System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic);
object[] attrs = mi.GetCustomAttributes(true);
foreach (object attr in attrs)
{
DynamicDllImportAttribute importAttr = attr as DynamicDllImportAttribute;
if (importAttr != null)
{
System.Console.WriteLine(importAttr.Name);
}
} // Next attr
} // End Sub Test
} // End Class
} // End Namespace
Related
I'm implementing Interceptor mechanism in .NET with Castle.DynamicProxy (Castle.Core 4.4.0). I'm following this tutorial for selecting which method to intercept: https://kozmic.net/2009/01/17/castle-dynamic-proxy-tutorial-part-iii-selecting-which-methods-to/
It was given an example in this article about "selecting which methods to intercept":
public class FreezableProxyGenerationHook:IProxyGenerationHook
{
public bool ShouldInterceptMethod(Type type, MethodInfo memberInfo)
{
return !memberInfo.Name.StartsWith("get_", StringComparison.Ordinal);
}
//implementing other methods...
}
According to this article, I implemented the ShouldInterceptMethod like below but i can not access the method's custom attributes.
public class ProductServiceProxyGenerationHook : IProxyGenerationHook
{
public void MethodsInspected()
{
}
public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
{
}
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
//return methodInfo.CustomAttributes.Any(a => a.GetType() == typeof(UseInterceptorAttribute));
return methodInfo.CustomAttributes.Count() > 0;
}
}
This is the method that i want to intercept:
[UseInterceptor]
public Product AOP_Get(string serialNumber)
{
throw new NotImplementedException();
}
This is my custom attribute:
[System.AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
sealed class UseInterceptorAttribute : Attribute
{
public UseInterceptorAttribute()
{
}
}
When ShouldInterceptMethod invoked for AOP_Get method, there aren't any custom attributes on local variable methodInfo. As a result ShouldInterceptMethod returns false. But when i check from the AOP_Get method body, i can access custom attribute like below:
How can i access custom attributes in ShouldInterceptMethod method?
I solved the problem using UseInterceptorAttribute in the interface methods. Because the interceptor is enabling for interface:
//autofac
var proxyGenerationOptions = new ProxyGenerationOptions(new ProductServiceProxyGenerationHook());
builder.RegisterType<ProductService>()
.As<IProductService>()
.EnableInterfaceInterceptors(proxyGenerationOptions)
.InterceptedBy(typeof(LoggingInterceptor));
The solution:
public interface IProductService
{
Product Get(string productNumber, string serialNumber);
bool Create(string productNumber, string serialNumber);
[UseInterceptor]
Product AOP_Get(string productNumber, string serialNumber);
}
public class ProductService : IProductService
{
public Product AOP_Get(string productNumber, string serialNumber)
{
var m = GetType().GetMethod("AOP_Get");
return null;
}
public bool Create(string productNumber, string serialNumber)
{
return true;
}
public Product Get(string productNumber, string serialNumber)
{
return new Product
{
Id = 5,
ProductNumber = "testPN",
SerialNumber = "testSN"
};
}
}
public class ProductServiceProxyGenerationHook : IProxyGenerationHook
{
public void MethodsInspected()
{
}
public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
{
}
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
return methodInfo
.CustomAttributes
.Any(a => a.AttributeType == typeof(UseInterceptorAttribute));
}
}
}
Why I ran into this issue is shown with an example below with KnownValueDefinition<T> where ideally I would like to be able to output a List<KnownValueDefinition<object>> from a static class with a bunch of static readonly KnownValueDefinition<T>s
var reflectedFields =
typeof(KnownValue)
.GetFields( BindingFlags.Static | BindingFlags.Public )
.Where( p => p.FieldType.GetGenericTypeDefinition() == typeof(KnownValueDefinition<>) );
foreach( var fieldInfo in reflectedFields )
{
object value = fieldInfo.GetValue( null );
// every conversion method I've tried here fails...
}
where KnownValueDefinition<T> is basically defined as:
public class KnownValueDefinition<T>
{
// .. private members excluded for brevity
public string Key { get { return _key; } }
public T DefaultValue { get { return _defaultValue; } }
}
The short answer is NO.
Given two classes:
class BaseClass { ... }
class DerivedClass : BaseClass { ... }
and a generic class
class Widget<T> { ... }
It's instantiations
Widget<BaseClass> {...}
Widget<DerivedClass> { ... }
are pretty much treated as independent classes. You can't "upcast" like this:
Widget<DerivedClass> instance = new Widget<DerivedClass>() ;
Widget<BaseClass> upcastInstance = (Widget<DerivedClass>)instance ;
even though it seems like a perfectl sane thing to want to do.
Further, C# (and the CLR?) has no way of saying something like
Widget<?> = instance = ... ;
to indicate that all I care about is the fact that it is some instance of Widget<T>, but that I don't care about the type of T.
There's lots of questions (and answers) on this topic: just search.
You can define and implement a covariant interface:
public interface IKnownValueDefinition<out T>
{
public string Key { get; }
public T DefaultValue { get; }
}
public class KnownValueDefinition<T> : IKnownValueDefinition<T>
{
// .. private members excluded for brevity
public string Key { get { return _key; } }
public T DefaultValue { get { return _defaultValue; } }
}
Usage:
var kvdSomeClass = new KnownValueDefinition<SomeClass>();
IKnownValueDefinition<object> kvdObject = kvd; // this works
// but this will not work
var kvdInt = newKnownValueDefinition<int>();
kvdObject = kvdInt;
Covariance & Contravariance MSDN Page
Alexei's comment gave me an idea that appears to work perfectly (at least for my purposes)!:
public class KnownValueDefinition<T> :
IKnownValueDefinition
, IKnownValueDefinition<T>
{
// .. private members excluded for brevity
public string Key { get { return _key; } }
public T DefaultValue { get { return _defaultValue; } }
public KnownValueDefinition( string key, T DefaultValue )
{
//...construction logic
}
public IKnownValueDefinition<object> GetDefault()
{
return new KnownValueDefinition<object>( this._key, this._defaultValue );
}
}
public interface IKnownValueDefinition
{
IKnownValueDefinition<object> GetDefault();
}
public interface IKnownValueDefinition<out T>
{
string Key { get; }
T DefaultValue { get; }
}
and to complete this with the usage scenario:
var knownValueDefinitions = new List<IKnownValueDefinition<object>>();
var reflectedFields =
typeof(KnownValue)
.GetFields( BindingFlags.Static | BindingFlags.Public )
.Where( p => p.FieldType.GetGenericTypeDefinition() == typeof(KnownValueDefinition<>) );
foreach( var value in reflectedFields.Select( fieldInfo => fieldInfo.GetValue( null ) ) )
KnownValueDefinitions.Add( ((IKnownValueDefinition)value).GetDefault() );
I have occasionally had cause to write collection class adapters, i.e. create an adapter for a class that implements IList<T> proxying its methods, whist adding some extra functionality. The IList interface has numerous methods / properties, I was wondering whether the straight-through proxy methods could be implemented dynamically? I had a look at DynamicObject, but could only find a few simple examples that proxy DTO classes, i.e. proxying a class that just has properties.
Is the proxying of IList<T> possible?
e.g.
public class ListProxy : IList<T>
{
private IList<T> _adaptee;
public ListProxy(IList<T> adaptee)
{
_adaptee = adaptee
}
// dynamically implement straight-through IList methods / properties
}
Something like this?
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
class Program
{
static void Main(string[] args)
{
IList<string> listProxy = MyProxyGenerator.Create<IList<string>>(new ListProxy<string>(new List<string>() { "aa","bb" }));
bool b1 = listProxy.Contains("aa");
bool b2 = listProxy.Contains("cc");
int count = listProxy.Count;
string s = listProxy[1];
}
public class ListProxy<T>
{
private IList<T> _adaptee;
//Only method needed by proxy generator
object Adaptee
{
get { return _adaptee; }
}
public ListProxy(IList<T> adaptee)
{
_adaptee = adaptee;
}
}
class MyProxyGenerator : RealProxy
{
Type _Type;
object _Instance;
public static T Create<T>(object instance)
{
return (T)new MyProxyGenerator(typeof(T),instance).GetTransparentProxy();
}
MyProxyGenerator(Type type,object instance) : base(type)
{
_Type = type;
_Instance = instance.GetType().InvokeMember("get_Adaptee", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, instance, null);
}
public override IMessage Invoke(IMessage msg)
{
IMethodCallMessage methodMessage = new MethodCallMessageWrapper((IMethodCallMessage)msg);
string method = (string)msg.Properties["__MethodName"];
object[] args = (object[])msg.Properties["__Args"];
object retObj = _Instance.GetType().InvokeMember(method, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,null,_Instance,args);
return new ReturnMessage(retObj,methodMessage.Args,methodMessage.ArgCount,methodMessage.LogicalCallContext,methodMessage);
}
}
}
HI All,
I need to access the class SomeClass which is declared has a private field in the Wrapper class, using Reflection so far i have been able to get private field members . How do i cast it back to its original type so that i could access it properties and other members.
internal class Program
{
private static void Main(string[] args)
{
Wrapper wrap = new Wrapper
{
SOmeProperty = new SomeClass
{
Number = 007
}
};
Type type = wrap.GetType();
FieldInfo[] infos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var item in infos)
{
}
}
}
internal class SomeClass
{
public int Number { get; set; }
}
internal class Wrapper
{
private SomeClass _tempSomeObj;
public SomeClass SOmeProperty
{
get
{
return _tempSomeObj;
}
set
{
_tempSomeObj = value;
}
}
}
I dont know if i understand the question correct. You want the type of the private field (backing field)??
Then you could check the FieldType property of the FieldInfo....
like this:
internal class Program
{
#region Methods
private static void Main(string[] args)
{
var wrap = new Wrapper { SOmeProperty = new SomeClass { Number = 007 } };
Type type = wrap.GetType();
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var fieldInfo in fieldInfos)
{
if (fieldInfo.FieldType == typeof(SomeClass))
{
Console.WriteLine("Yap!");
}
}
}
#endregion
}
internal class SomeClass
{
#region Properties
public int Number { get; set; }
#endregion
}
internal class Wrapper
{
#region Properties
public SomeClass SOmeProperty { get; set; }
#endregion
}
Use PropertyInfo instead:
internal class Program
{
private static void Main(string[] args)
{
Wrapper wrap = new Wrapper
{
SOmeProperty = new SomeClass
{
Number = 007
}
};
Type type = wrap.GetType();
PropertyInfo info = type.GetProperty("SOmeProperty", BindingFlags.NonPublic | BindingFlags.Instance);
SomeClass value = (SomeClass)info.GetValue(wrap, null);
// use `value` variable here
}
}
I'm still a little fuzzy about what your're trying to do, but you can always GetType() on any object and get its actual run time type and query that for properties field of some other type for example
public void ListPropertiesOfType( object targetObject, Type propertyType ) {
foreach( var foundProperty in targetObject.GetType( ).GetProperties( ).Where( p => p.PropertyType == propertyType ) ) {
Console.WriteLine( "Name: {0}, Value: {1}", foundProperty.Name, foundProperty.GetValue( targetObject, null ) );
}
}
ListPropertiesOfType(new Wrapper(), typeof(SomeClass))
ListPropertiesOfType(new Wrapper(), typeof(SomeOtherClass))
If you want to pass in instances of Someclass and SomeClass that is also fine, just use GetType() on the instances to get the type that you can then use to find properties of that type as illustrated above. this works the same way regardless if you make the method generic and pass in "T" or if its non-generic and you pass in "object"
Is there any way to move the Parse method into the abstract class ? I tried multiple ways (links at the bottom), but I am still hitting one or another roadblock.
public class AnimalEntityId : EntityId<AnimalEntityId>
{
public AnimalEntityId()
: base()
{
}
private AnimalEntityId(string value)
: base(value)
{
}
public static AnimalEntityId Parse(string value)
{
return new AnimalEntityId(value);
}
}
public abstract class EntityId<TEntityId>
{
private readonly System.Guid value;
protected EntityId(string value)
{
this.value = System.Guid.Parse(value);
}
protected EntityId()
{
this.value = System.Guid.NewGuid();
}
}
Tried these suggestions with no luck:
Passing arguments to C# generic new() of templated type
Is there a generic constructor with parameter constraint in C#?
https://social.msdn.microsoft.com/Forums/en-US/fd43d184-0503-4d4a-850c-999ca58e1444/creating-generic-t-with-new-constraint-that-has-parameters?forum=csharplanguage
http://www.gamedev.net/topic/577668-c-new-constraint--is-it-possible-to-add-parameters/
Thanks in advance!
If you don't mind using reflection, you can move Parse into the abstract type like this:
public static TEntityId Parse(string val) {
var constr = typeof(TEntityId).GetConstructor(
// Since the constructor is private, you need binding flags
BindingFlags.Instance | BindingFlags.NonPublic
, null
, new[]{ typeof(string) }
, null);
if (constr == null) {
throw new InvalidOperationException("No constructor");
}
return (TEntityId)constr.Invoke(new object[] {val});
}
Demo.
No, you cannot write a template constraint such as new(string) instead of simply new(). You'll have to leverage reflection to get it to work:
public abstract class EntityId<TEntityId>
where TEntityId : EntityId<TEntityId>
{
private readonly System.Guid value;
protected EntityId(string value)
{
this.value = System.Guid.Parse(value);
}
protected EntityId()
{
this.value = System.Guid.NewGuid();
}
public static TEntityId Parse(string value)
{
return (TEntityId)Activator.CreateInstance(typeof(TEntityId), new object[] { value });
}
}
Assuming you make the constructor accessible (instead of it currently being private). Note the constraint where TEntityId : EntityId<TEntityId> - which will ensure we'll only return subclasses of EntityId
How about making value a private mutable field/property and actually setting it from the Parse method?
(Curiously recurring generic parameter removed from EntityId for simplicity)
public class SimpleAnimalEntityId : EntityId
{
// Implicit parameterless constructor.
}
public class ParametrizedAnimalEntityId : EntityId
{
// Parametrized constructor only.
public ParametrizedAnimalEntityId(int ignored)
{
}
}
public abstract class EntityId
{
// Simple scenario: derived type has a parameterless constructor.
public static TEntity Parse<TEntity>(string value)
where TEntity : EntityId, new()
{
Guid id = Guid.Parse(value);
return new TEntity { value = id };
}
// Advanced scenario: derived type constructor needs parameters injected.
public static TEntity Parse<TEntity>(string value, Func<TEntity> constructor)
where TEntity : EntityId
{
Guid id = Guid.Parse(value);
TEntity entity = constructor();
entity.value = id;
return entity;
}
private Guid value;
protected EntityId()
{
value = Guid.NewGuid();
}
}
Now you can handle any constructor from your Parse method:
string id = Guid.NewGuid().ToString();
SimpleAnimalEntityId simple = EntityId.Parse<SimpleAnimalEntityId>(id);
ParametrizedAnimalEntityId parametrized = EntityId.Parse(id, () => new ParametrizedAnimalEntityId(42));