C# Language
प्रतिबिंब
खोज…
परिचय
परावर्तन रनटाइम पर गतिशील वस्तु गुणों तक पहुँचने के लिए एक C # भाषा तंत्र है। आमतौर पर, प्रतिबिंब का उपयोग गतिशील वस्तु प्रकार और ऑब्जेक्ट विशेषता मानों के बारे में जानकारी प्राप्त करने के लिए किया जाता है। अन्य एप्लिकेशन में, उदाहरण के लिए, प्रतिबिंब को क्रमबद्ध प्रतिक्रिया ऑब्जेक्ट के माध्यम से पुनरावृति करने के लिए इस्तेमाल किया जा सकता है।
टिप्पणी: एमएस दिशा-निर्देशों के प्रदर्शन के अनुसार, महत्वपूर्ण कोड को प्रतिबिंब से बचना चाहिए। Https://msdn.microsoft.com/en-us/library/ff647790.aspx देखें
टिप्पणियों
प्रतिबिंब रन-टाइम (प्रोग्राम निष्पादन) पर कोड को असेंबली, मॉड्यूल और प्रकारों के बारे में जानकारी तक पहुंचने की अनुमति देता है। फिर इसे गतिशील रूप से बनाने, संशोधित करने या एक्सेस करने के लिए उपयोग किया जा सकता है। प्रकारों में गुण, विधियाँ, क्षेत्र और विशेषताएँ शामिल हैं।
आगे की पढाई :
एक System.Type प्राप्त करें
एक प्रकार की आवृत्ति के लिए:
var theString = "hello";
var theType = theString.GetType();
प्रकार से ही:
var theType = typeof(string);
एक प्रकार के सदस्य प्राप्त करें
using System;
using System.Reflection;
using System.Linq;
public class Program
{
public static void Main()
{
var members = typeof(object)
.GetMembers(BindingFlags.Public |
BindingFlags.Static |
BindingFlags.Instance);
foreach (var member in members)
{
bool inherited = member.DeclaringType.Equals( typeof(object).Name );
Console.WriteLine($"{member.Name} is a {member.MemberType}, " +
$"it has {(inherited ? "":"not")} been inherited.");
}
}
}
आउटपुट ( आउटपुट ऑर्डर के बारे में नोट नीचे देखें ):
GetType is a Method, it has not been inherited. GetHashCode is a Method, it has not been inherited. ToString is a Method, it has not been inherited. Equals is a Method, it has not been inherited. Equals is a Method, it has not been inherited. ReferenceEquals is a Method, it has not been inherited. .ctor is a Constructor, it has not been inherited.
हम यह भी उपयोग कर सकते हैं GetMembers()
किसी भी गुजर बिना BindingFlags
। यह उस विशिष्ट प्रकार के सभी सार्वजनिक सदस्यों को लौटा देगा।
एक बात ध्यान रखें कि GetMembers
सदस्यों को किसी विशेष क्रम में वापस नहीं करता है, इसलिए कभी भी उस आदेश पर भरोसा न करें जो GetMembers
आपको लौटाता है।
एक विधि प्राप्त करें और इसे लागू करें
इंस्टेंस विधि प्राप्त करें और इसे लागू करें
using System;
public class Program
{
public static void Main()
{
var theString = "hello";
var method = theString
.GetType()
.GetMethod("Substring",
new[] {typeof(int), typeof(int)}); //The types of the method arguments
var result = method.Invoke(theString, new object[] {0, 4});
Console.WriteLine(result);
}
}
आउटपुट:
नरक
स्टैटिक विधि प्राप्त करें और इसे लागू करें
दूसरी ओर, यदि विधि स्थिर है, तो आपको इसे कॉल करने के लिए किसी इंस्टेंस की आवश्यकता नहीं है।
var method = typeof(Math).GetMethod("Exp");
var result = method.Invoke(null, new object[] {2});//Pass null as the first argument (no need for an instance)
Console.WriteLine(result); //You'll get e^2
आउटपुट:
7.38905609893065
गुण प्राप्त करना और स्थापित करना
मूल उपयोग:
PropertyInfo prop = myInstance.GetType().GetProperty("myProperty");
// get the value myInstance.myProperty
object value = prop.GetValue(myInstance);
int newValue = 1;
// set the value myInstance.myProperty to newValue
prop.setValue(myInstance, newValue);
रीड-ओनली-इंप्लीमेंटेड प्रॉपर्टीज़ को सेट करना इसके बैकिंग फील्ड के माध्यम से किया जा सकता है (बैकिंग फ़ील्ड का .NET फ्रेमवर्क नाम "k__BackingField" है):
// get backing field info
FieldInfo fieldInfo = myInstance.GetType()
.GetField("<myProperty>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
int newValue = 1;
// set the value of myInstance.myProperty backing field to newValue
fieldInfo.SetValue(myInstance, newValue);
कस्टम विशेषताएँ
एक कस्टम विशेषता के साथ गुण खोजें - MyAttribute
var props = t.GetProperties(BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Instance).Where(
prop => Attribute.IsDefined(prop, typeof(MyAttribute)));
किसी दी गई संपत्ति पर सभी कस्टम विशेषताएँ खोजें
var attributes = typeof(t).GetProperty("Name").GetCustomAttributes(false);
कस्टम विशेषता के साथ सभी वर्गों की गणना करें - MyAttribute
static IEnumerable<Type> GetTypesWithAttribute(Assembly assembly) {
foreach(Type type in assembly.GetTypes()) {
if (type.GetCustomAttributes(typeof(MyAttribute), true).Length > 0) {
yield return type;
}
}
}
रनटाइम पर एक कस्टम विशेषता का मान पढ़ें
public static class AttributeExtensions
{
/// <summary>
/// Returns the value of a member attribute for any member in a class.
/// (a member is a Field, Property, Method, etc...)
/// <remarks>
/// If there is more than one member of the same name in the class, it will return the first one (this applies to overloaded methods)
/// </remarks>
/// <example>
/// Read System.ComponentModel Description Attribute from method 'MyMethodName' in class 'MyClass':
/// var Attribute = typeof(MyClass).GetAttribute("MyMethodName", (DescriptionAttribute d) => d.Description);
/// </example>
/// <param name="type">The class that contains the member as a type</param>
/// <param name="MemberName">Name of the member in the class</param>
/// <param name="valueSelector">Attribute type and property to get (will return first instance if there are multiple attributes of the same type)</param>
/// <param name="inherit">true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events</param>
/// </summary>
public static TValue GetAttribute<TAttribute, TValue>(this Type type, string MemberName, Func<TAttribute, TValue> valueSelector, bool inherit = false) where TAttribute : Attribute
{
var att = type.GetMember(MemberName).FirstOrDefault().GetCustomAttributes(typeof(TAttribute), inherit).FirstOrDefault() as TAttribute;
if (att != null)
{
return valueSelector(att);
}
return default(TValue);
}
}
प्रयोग
//Read System.ComponentModel Description Attribute from method 'MyMethodName' in class 'MyClass'
var Attribute = typeof(MyClass).GetAttribute("MyMethodName", (DescriptionAttribute d) => d.Description);
एक वर्ग के सभी गुणों के माध्यम से लूपिंग
Type type = obj.GetType();
//To restrict return properties. If all properties are required don't provide flag.
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
PropertyInfo[] properties = type.GetProperties(flags);
foreach (PropertyInfo property in properties)
{
Console.WriteLine("Name: " + property.Name + ", Value: " + property.GetValue(obj, null));
}
सामान्य प्रकार के उदाहरणों के सामान्य तर्कों का निर्धारण करना
यदि आपके पास जेनेरिक प्रकार का उदाहरण है, लेकिन किसी कारण से विशिष्ट प्रकार का पता नहीं है, तो आप जेनेरिक तर्कों को निर्धारित करना चाहते हैं जो इस उदाहरण को बनाने के लिए उपयोग किए गए थे।
मान लें कि किसी ने List<T>
का एक उदाहरण बनाया है और इसे एक विधि से पास करता है:
var myList = new List<int>();
ShowGenericArguments(myList);
जहाँ ShowGenericArguments
में यह हस्ताक्षर हैं:
public void ShowGenericArguments(object o)
इसलिए संकलन के समय आपके पास कोई विचार नहीं है कि o
बनाने के लिए जेनेरिक तर्कों का क्या उपयोग किया गया है। प्रतिबिंब जेनेरिक प्रकारों का निरीक्षण करने के लिए कई तरीके प्रदान करता है। सबसे पहले, हम निर्धारित कर सकते हैं कि o
का प्रकार एक सामान्य प्रकार है:
public void ShowGenericArguments(object o)
{
if (o == null) return;
Type t = o.GetType();
if (!t.IsGenericType) return;
...
Type.IsGenericType
true
यदि प्रकार एक सामान्य प्रकार है और यदि नहीं तो false
।
लेकिन यह सब हम नहीं जानना चाहते हैं। List<>
स्वयं भी एक सामान्य प्रकार है। लेकिन हम केवल विशिष्ट निर्मित सामान्य प्रकारों के उदाहरणों की जांच करना चाहते हैं। एक निर्मित जेनेरिक प्रकार उदाहरण के लिए एक List<int>
है जिसमें उसके सभी जेनेरिक मापदंडों के लिए एक विशिष्ट प्रकार का तर्क है ।
Type
वर्ग दो और गुण प्रदान करता है, IsConstructedGenericType
और IsGenericTypeDefinition
, इन प्रकार के सामान्य प्रकार को सामान्य प्रकार की परिभाषाओं से अलग करने के लिए:
typeof(List<>).IsGenericType // true
typeof(List<>).IsGenericTypeDefinition // true
typeof(List<>).IsConstructedGenericType// false
typeof(List<int>).IsGenericType // true
typeof(List<int>).IsGenericTypeDefinition // false
typeof(List<int>).IsConstructedGenericType// true
किसी उदाहरण के जेनेरिक तर्कों की गणना करने के लिए, हम GetGenericArguments()
विधि का उपयोग कर सकते हैं जो जेनेरिक प्रकार के तर्कों वाले एक Type
सरणी देता है:
public void ShowGenericArguments(object o)
{
if (o == null) return;
Type t = o.GetType();
if (!t.IsConstructedGenericType) return;
foreach(Type genericTypeArgument in t.GetGenericArguments())
Console.WriteLine(genericTypeArgument.Name);
}
तो ऊपर से कॉल ( ShowGenericArguments(myList)
) इस आउटपुट में परिणाम:
Int32
एक सामान्य विधि प्राप्त करें और इसे लागू करें
मान लीजिए कि आपके पास सामान्य तरीके हैं। और आपको प्रतिबिंब के साथ इसके कार्यों को कॉल करने की आवश्यकता है।
public class Sample
{
public void GenericMethod<T>()
{
// ...
}
public static void StaticMethod<T>()
{
//...
}
}
मान लीजिए कि हम GenericMethod को स्ट्रिंग के साथ कॉल करना चाहते हैं।
Sample sample = new Sample();//or you can get an instance via reflection
MethodInfo method = typeof(Sample).GetMethod("GenericMethod");
MethodInfo generic = method.MakeGenericMethod(typeof(string));
generic.Invoke(sample, null);//Since there are no arguments, we are passing null
स्थिर विधि के लिए आपको एक उदाहरण की आवश्यकता नहीं है। इसलिए पहला तर्क भी अशक्त होगा।
MethodInfo method = typeof(Sample).GetMethod("StaticMethod");
MethodInfo generic = method.MakeGenericMethod(typeof(string));
generic.Invoke(null, null);
एक जेनेरिक प्रकार का एक उदाहरण बनाएँ और इसे लागू करें विधि
var baseType = typeof(List<>);
var genericType = baseType.MakeGenericType(typeof(String));
var instance = Activator.CreateInstance(genericType);
var method = genericType.GetMethod("GetHashCode");
var result = method.Invoke(instance, new object[] { });
एक इंटरफ़ेस लागू करने वाली त्वरित कक्षाएं (जैसे प्लगइन सक्रियण)
आप अपने आवेदन समर्थन करना चाहते हैं एक प्लग-इन प्रणाली में स्थित विधानसभाओं से लोड प्लगइन्स उदाहरण के लिए plugins
फ़ोल्डर:
interface IPlugin
{
string PluginDescription { get; }
void DoWork();
}
यह वर्ग एक अलग dll में स्थित होगा
class HelloPlugin : IPlugin
{
public string PluginDescription => "A plugin that says Hello";
public void DoWork()
{
Console.WriteLine("Hello");
}
}
आपके एप्लिकेशन के प्लगइन लोडर को dll फाइलें IPlugin
, उन सभी प्रकार की असेंबली में IPlugin
जो IPlugin
लागू IPlugin
, और उन लोगों के इंस्टेंस बनाते हैं।
public IEnumerable<IPlugin> InstantiatePlugins(string directory)
{
var pluginAssemblyNames = Directory.GetFiles(directory, "*.addin.dll").Select(name => new FileInfo(name).FullName).ToArray();
//load the assemblies into the current AppDomain, so we can instantiate the types later
foreach (var fileName in pluginAssemblyNames)
AppDomain.CurrentDomain.Load(File.ReadAllBytes(fileName));
var assemblies = pluginAssemblyNames.Select(System.Reflection.Assembly.LoadFile);
var typesInAssembly = assemblies.SelectMany(asm => asm.GetTypes());
var pluginTypes = typesInAssembly.Where(type => typeof (IPlugin).IsAssignableFrom(type));
return pluginTypes.Select(Activator.CreateInstance).Cast<IPlugin>();
}
एक प्रकार का उदाहरण बनाना
सबसे सरल तरीका Activator
क्लास का उपयोग करना है।
हालाँकि, भले ही Activator
Activator.CreateInstance()
का कभी-कभी खराब विकल्प हो, (अपेक्षाकृत) कम प्रदर्शन: टेस्ट 1 , टेस्ट 2 , टेस्ट 3 ...
Activator
वर्ग के साथ
Type type = typeof(BigInteger);
object result = Activator.CreateInstance(type); //Requires parameterless constructor.
Console.WriteLine(result); //Output: 0
result = Activator.CreateInstance(type, 123); //Requires a constructor which can receive an 'int' compatible argument.
Console.WriteLine(result); //Output: 123
यदि आप एक से अधिक पैरामीटर रखते हैं, तो आप Activator.CreateInstance
ऑब्जेक्ट ऐरे पास कर सकते हैं।
// With a constructor such as MyClass(int, int, string)
Activator.CreateInstance(typeof(MyClass), new object[] { 1, 2, "Hello World" });
Type type = typeof(someObject);
var instance = Activator.CreateInstance(type);
एक सामान्य प्रकार के लिए
MakeGenericType
पद्धति एक खुले जेनेरिक प्रकार (जैसे List<>
) को एक ठोस प्रकार (जैसे List<string>
) में MakeGenericType
उस पर तर्क देती है।
// generic List with no parameters
Type openType = typeof(List<>);
// To create a List<string>
Type[] tArgs = { typeof(string) };
Type target = openType.MakeGenericType(tArgs);
// Create an instance - Activator.CreateInstance will call the default constructor.
// This is equivalent to calling new List<string>().
List<string> result = (List<string>)Activator.CreateInstance(target);
typeof
अभिव्यक्ति के बाहर List<>
वाक्यविन्यास की अनुमति नहीं है।
Activator
वर्ग के बिना
new
कीवर्ड का उपयोग करना (पैरामीटर रहित निर्माणकर्ताओं के लिए करेगा)
T GetInstance<T>() where T : new()
{
T instance = new T();
return instance;
}
चालान विधि का उपयोग करना
// Get the instance of the desired constructor (here it takes a string as a parameter).
ConstructorInfo c = typeof(T).GetConstructor(new[] { typeof(string) });
// Don't forget to check if such constructor exists
if (c == null)
throw new InvalidOperationException(string.Format("A constructor for type '{0}' was not found.", typeof(T)));
T instance = (T)c.Invoke(new object[] { "test" });
अभिव्यक्ति पेड़ों का उपयोग करना
अभिव्यक्ति के पेड़ एक पेड़ की तरह डेटा संरचना में कोड का प्रतिनिधित्व करते हैं, जहां प्रत्येक नोड एक अभिव्यक्ति है। जैसा कि MSDN बताता है:
अभिव्यक्ति एक या एक से अधिक ऑपरेंड और शून्य या अधिक ऑपरेटरों का एक अनुक्रम है जिसका मूल्यांकन किसी एकल मान, ऑब्जेक्ट, विधि या नाम स्थान पर किया जा सकता है। अभिव्यक्तियों में शाब्दिक मूल्य, एक विधि आह्वान, एक ऑपरेटर और उसके ऑपरेंड या एक साधारण नाम शामिल हो सकते हैं। सरल नाम एक चर, प्रकार सदस्य, विधि पैरामीटर, नाम स्थान या प्रकार का नाम हो सकता है।
public class GenericFactory<TKey, TType>
{
private readonly Dictionary<TKey, Func<object[], TType>> _registeredTypes; // dictionary, that holds constructor functions.
private object _locker = new object(); // object for locking dictionary, to guarantee thread safety
public GenericFactory()
{
_registeredTypes = new Dictionary<TKey, Func<object[], TType>>();
}
/// <summary>
/// Find and register suitable constructor for type
/// </summary>
/// <typeparam name="TType"></typeparam>
/// <param name="key">Key for this constructor</param>
/// <param name="parameters">Parameters</param>
public void Register(TKey key, params Type[] parameters)
{
ConstructorInfo ci = typeof(TType).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.HasThis, parameters, new ParameterModifier[] { }); // Get the instance of ctor.
if (ci == null)
throw new InvalidOperationException(string.Format("Constructor for type '{0}' was not found.", typeof(TType)));
Func<object[], TType> ctor;
lock (_locker)
{
if (!_registeredTypes.TryGetValue(key, out ctor)) // check if such ctor already been registered
{
var pExp = Expression.Parameter(typeof(object[]), "arguments"); // create parameter Expression
var ctorParams = ci.GetParameters(); // get parameter info from constructor
var argExpressions = new Expression[ctorParams.Length]; // array that will contains parameter expessions
for (var i = 0; i < parameters.Length; i++)
{
var indexedAcccess = Expression.ArrayIndex(pExp, Expression.Constant(i));
if (!parameters[i].IsClass && !parameters[i].IsInterface) // check if parameter is a value type
{
var localVariable = Expression.Variable(parameters[i], "localVariable"); // if so - we should create local variable that will store paraameter value
var block = Expression.Block(new[] { localVariable },
Expression.IfThenElse(Expression.Equal(indexedAcccess, Expression.Constant(null)),
Expression.Assign(localVariable, Expression.Default(parameters[i])),
Expression.Assign(localVariable, Expression.Convert(indexedAcccess, parameters[i]))
),
localVariable
);
argExpressions[i] = block;
}
else
argExpressions[i] = Expression.Convert(indexedAcccess, parameters[i]);
}
var newExpr = Expression.New(ci, argExpressions); // create expression that represents call to specified ctor with the specified arguments.
_registeredTypes.Add(key, Expression.Lambda(newExpr, new[] { pExp }).Compile() as Func<object[], TType>); // compile expression to create delegate, and add fucntion to dictionary
}
}
}
/// <summary>
/// Returns instance of registered type by key.
/// </summary>
/// <typeparam name="TType"></typeparam>
/// <param name="key"></param>
/// <param name="args"></param>
/// <returns></returns>
public TType Create(TKey key, params object[] args)
{
Func<object[], TType> foo;
if (_registeredTypes.TryGetValue(key, out foo))
{
return (TType)foo(args);
}
throw new ArgumentException("No type registered for this key.");
}
}
इस तरह इस्तेमाल किया जा सकता है:
public class TestClass
{
public TestClass(string parameter)
{
Console.Write(parameter);
}
}
public void TestMethod()
{
var factory = new GenericFactory<string, TestClass>();
factory.Register("key", typeof(string));
TestClass newInstance = factory.Create("key", "testParameter");
}
FormatterServices.GetUninitializedObject का उपयोग करना
T instance = (T)FormatterServices.GetUninitializedObject(typeof(T));
FormatterServices.GetUninitializedObject
कंस्ट्रक्टर्स और फ़ील्ड इनिशियलाइज़र का उपयोग करने के मामले में नहीं बुलाया जाएगा। इसका उपयोग धारावाहिकों और रीमोटिंग इंजनों में किया जाना है
नेमस्पेस के साथ नाम से एक प्रकार प्राप्त करें
ऐसा करने के लिए आपको विधानसभा के संदर्भ की आवश्यकता होती है जिसमें प्रकार होता है। यदि आपके पास एक और प्रकार उपलब्ध है, जिसे आप जानते हैं कि वह उसी विधानसभा में है, जैसा आप चाहते हैं कि आप ऐसा कर सकते हैं:
typeof(KnownType).Assembly.GetType(typeName);
- जहाँ
typeName
उस प्रकार का नाम है जिसे आप (नेमस्पेस सहित) खोज रहे हैं, औरKnownType
वह प्रकार है जिसे आप जानते हैं कि वह एक ही असेंबली में है।
कम कुशल लेकिन अधिक सामान्य इस प्रकार है:
Type t = null;
foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies())
{
if (ass.FullName.StartsWith("System."))
continue;
t = ass.GetType(typeName);
if (t != null)
break;
}
खोज को तेज करने के लिए सिस्टम नेमस्पेस असेंबलियों को स्कैन करने के लिए चेक को नोटिस करें। यदि आपका प्रकार वास्तव में सीएलआर प्रकार हो सकता है, तो आपको इन दो लाइनों को हटाना होगा।
यदि आप पूरी तरह से असेंबली-योग्य-प्रकार का नाम रखते हैं, जिसमें असेंबली शामिल है, तो आप इसे आसानी से प्राप्त कर सकते हैं
Type.GetType(fullyQualifiedName);
परावर्तन के माध्यम से एक विधि या संपत्ति के लिए एक मजबूत टाइप प्रतिनिधि प्राप्त करें
जब प्रदर्शन एक चिंता का विषय है, तो प्रतिबिंब के माध्यम से एक विधि को लागू करना (अर्थात MethodInfo.Invoke
विधि के माध्यम से) आदर्श नहीं है। हालाँकि, यह Delegate.CreateDelegate
फ़ंक्शन का उपयोग करके एक अधिक प्रदर्शन करने वाले दृढ़ता से टाइप किए गए प्रतिनिधि को प्राप्त करने के लिए अपेक्षाकृत सरल है। प्रतिबिंब का उपयोग करने के लिए प्रदर्शन दंड केवल प्रतिनिधि-निर्माण प्रक्रिया के दौरान ही होता है। एक बार प्रतिनिधि तैयार हो जाने के बाद, इसे लागू करने के लिए कोई छोटा-मोटा प्रदर्शन नहीं होता है:
// Get a MethodInfo for the Math.Max(int, int) method...
var maxMethod = typeof(Math).GetMethod("Max", new Type[] { typeof(int), typeof(int) });
// Now get a strongly-typed delegate for Math.Max(int, int)...
var stronglyTypedDelegate = (Func<int, int, int>)Delegate.CreateDelegate(typeof(Func<int, int, int>), null, maxMethod);
// Invoke the Math.Max(int, int) method using the strongly-typed delegate...
Console.WriteLine("Max of 3 and 5 is: {0}", stronglyTypedDelegate(3, 5));
इस तकनीक को गुणों को भी बढ़ाया जा सकता है। हम एक वर्ग में नामित किया है, तो MyClass
एक साथ int
संपत्ति नामित MyIntProperty
, कोड प्राप्त करने के एक जोरदार टाइप गेटर होगा (निम्न उदाहरण मानता है 'लक्ष्य' का एक मान्य उदाहरण है MyClass
):
// Get a MethodInfo for the MyClass.MyIntProperty getter...
var theProperty = typeof(MyClass).GetProperty("MyIntProperty");
var theGetter = theProperty.GetGetMethod();
// Now get a strongly-typed delegate for MyIntProperty that can be executed against any MyClass instance...
var stronglyTypedGetter = (Func<MyClass, int>)Delegate.CreateDelegate(typeof(Func<MyClass, int>), theGetter);
// Invoke the MyIntProperty getter against MyClass instance 'target'...
Console.WriteLine("target.MyIntProperty is: {0}", stronglyTypedGetter(target));
... और सेटर के लिए भी यही किया जा सकता है:
// Get a MethodInfo for the MyClass.MyIntProperty setter...
var theProperty = typeof(MyClass).GetProperty("MyIntProperty");
var theSetter = theProperty.GetSetMethod();
// Now get a strongly-typed delegate for MyIntProperty that can be executed against any MyClass instance...
var stronglyTypedSetter = (Action<MyClass, int>)Delegate.CreateDelegate(typeof(Action<MyClass, int>), theSetter);
// Set MyIntProperty to 5...
stronglyTypedSetter(target, 5);