রানটাইমের সময় আমি কীভাবে কোনও ক্লাসে একটি গুণাবলী পড়তে পারি?


106

আমি একটি জেনেরিক পদ্ধতি তৈরি করার চেষ্টা করছি যা কোনও ক্লাসে একটি বৈশিষ্ট্য পড়বে এবং রানটাইমের সময় সেই মানটি ফিরিয়ে দেবে। আমি কীভাবে এটি করব?

দ্রষ্টব্য: ডোমেননাম অ্যাট্রিবিউট ডোমেননামঅ্যাট্রিবিউট শ্রেণীর।

[DomainName("MyTable")]
Public class MyClass : DomainBase
{}

আমি যা উত্পন্ন করার চেষ্টা করছি:

//This should return "MyTable"
String DomainNameValue = GetDomainName<MyClass>();

1
অফিসিয়াল মাইক্রোসফ্ট লিঙ্ক: এমএসডিএন.মাইক্রোসফটকম /en-us/library/71s1zwct.aspx
মহেশ

2
গুরুত্বপূর্ণ সম্পুরক প্রশ্ন কাস্টম অ্যাট্রিবিউট সঙ্গে সভায় সব ধরনের পেতে কিভাবে stackoverflow.com/questions/2656189/...
ক্রিস Marisic

উত্তর:


235
public string GetDomainName<T>()
{
    var dnAttribute = typeof(T).GetCustomAttributes(
        typeof(DomainNameAttribute), true
    ).FirstOrDefault() as DomainNameAttribute;
    if (dnAttribute != null)
    {
        return dnAttribute.Name;
    }
    return null;
}

হালনাগাদ:

এই পদ্ধতিটি আরও কোনও বৈশিষ্ট্যের সাথে কাজ করার জন্য আরও সাধারণীকরণ করা যেতে পারে:

public static class AttributeExtensions
{
    public static TValue GetAttributeValue<TAttribute, TValue>(
        this Type type, 
        Func<TAttribute, TValue> valueSelector) 
        where TAttribute : Attribute
    {
        var att = type.GetCustomAttributes(
            typeof(TAttribute), true
        ).FirstOrDefault() as TAttribute;
        if (att != null)
        {
            return valueSelector(att);
        }
        return default(TValue);
    }
}

এবং এটির মতো ব্যবহার করুন:

string name = typeof(MyClass)
    .GetAttributeValue((DomainNameAttribute dna) => dna.Name);

6
প্রশ্নের উত্তর দেওয়ার জন্য আপনার অধ্যবসায়ের জন্য ধন্যবাদ!
জাফিরো

1
এই এক্সটেনশন পদ্ধতিটি সদস্যপদগুলি, টাইপের একটি বেস ক্লাস এবং সমস্ত - বা কমপক্ষে বেশিরভাগ - কোনও টাইপের সদস্যদের দ্বারা বাড়িয়ে সাধারণীকরণ করা যেতে পারে । প্রপার্টি, ক্ষেত্রগুলি এবং ইভেন্টগুলি থেকে বৈশিষ্ট্যগুলি পড়ার অনুমতি দেওয়ার জন্য এটি করার ফলে এটি উন্মুক্ত হবে।
এমব্যাবকক

4
অতিরিক্ত জটিল বৈশিষ্ট্যটির মানটি নির্বাচন করতে ল্যাম্বদা ব্যবহার করার দরকার নেই। ল্যাম্বদা লেখার জন্য আপনার যথেষ্ট পরিমাণ থাকলে আপনি কেবল ক্ষেত্রটি অ্যাক্সেস করার জন্য যথেষ্ট জানেন।
ড্যারেল লি

const Filedস্থির শ্রেণিতে পেতে আমি কীভাবে এই পদ্ধতির প্রসার ঘটাতে পারি?
আমির

51

এটি করার জন্য ইতিমধ্যে একটি এক্সটেনশন রয়েছে।

namespace System.Reflection
{
    // Summary:
    //     Contains static methods for retrieving custom attributes.
    public static class CustomAttributeExtensions
    {
        public static T GetCustomAttribute<T>(this MemberInfo element, bool inherit) where T : Attribute;
    }
}

তাই:

var attr = typeof(MyClass).GetCustomAttribute<DomainNameAttribute>(false);
return attr != null ? attr.DomainName : "";

1
সত্য। তবে কেবল। নেট 4.5 এবং আরও নতুন। আমি এখনও লাইব্রেরির কোড বিকাশ করছি যেখানে আমি এই পদ্ধতিটি ব্যবহার করতে পারি না :(
অ্যান্ডরিজ

15
System.Reflection.MemberInfo info = typeof(MyClass);
object[] attributes = info.GetCustomAttributes(true);

for (int i = 0; i < attributes.Length; i++)
{
    if (attributes[i] is DomainNameAttribute)
    {
        System.Console.WriteLine(((DomainNameAttribute) attributes[i]).Name);
    }   
}

5
এবং "var" ব্যবহার না করার জন্য +1, সুতরাং এটি কীভাবে কাজ করে তা বোঝা সহজ।
রেনিপেট

এটি সংকলন করে না তবে "সিস্টেম.রিফ্লেশন.মেমিবার ইনফো তথ্য = টাইপফ (মাইক্লাস) GGetTypeInfo ();" কর
মার্সেল জেমস

4

আমি ক্লাসে যে কোনও সদস্যের জন্য সদস্যের গুণাবলী পেতে (জেনারিক বর্ধনের পরিবর্তে) জেনেরিক এক্সটেনশন তৈরি করতে ডারিন দিমিত্রভের উত্তরটি ব্যবহার করেছি। আমি এটি এখানে পোস্ট করছি কারণ অন্যরা এটি কার্যকর হতে পারে:

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);

উত্তরাধিকার উদ্ভূত বৈশিষ্ট্য কাজ করে না - যে, আপনি একটি পৃথক স্ট্যাটিক পদ্ধতি ডাকতে প্রয়োজন হবে (System.Attribute.GetCustomAttributes) stackoverflow.com/a/7175762/184910
murraybiscuit

3

দারিন দিমিত্রভের প্রথম সমাধানটির একটি সরল সংস্করণ:

public string GetDomainName<T>()
{
    var dnAttribute = typeof(T).GetCustomAttribute<DomainNameAttribute>(true);
    if (dnAttribute != null)
    {
        return dnAttribute.Name;
    }
    return null;
}

2

এখানে একটি ভাল টিউটোরিয়াল যদি আপনি এটি আগে কখনো দেখিনি? এর http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

আপনার আগ্রহের বিশেষত এখানে বিভাগটিকে বলা হয়, এটি অ্যাট্রিবিউট http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx#vcwlkattributestutorialanchor3


0
' Simplified Generic version. 
Shared Function GetAttribute(Of TAttribute)(info As MemberInfo) As TAttribute
    Return info.GetCustomAttributes(GetType(TAttribute), _
                                    False).FirstOrDefault()
End Function

' Example usage over PropertyInfo
Dim fieldAttr = GetAttribute(Of DataObjectFieldAttribute)(pInfo)
If fieldAttr IsNot Nothing AndAlso fieldAttr.PrimaryKey Then
    keys.Add(pInfo.Name)
End If

সম্ভবত জেনেরিক ফাংশন ইনলাইন এর শরীর ব্যবহার করা ঠিক তত সহজ। টাইপ মাইক্লাসের চেয়ে ফাংশনটি জেনেরিক করে তোলা আমার পক্ষে কোনও অর্থবোধ করে না।

string DomainName = GetAttribute<DomainNameAttribute>(typeof(MyClass)).Name
// null reference exception if MyClass doesn't have the attribute.

0

এনামস, প্রপার্টিআইএনফো এবং ক্লাস জুড়ে কাজ করার জন্য যদি কারও কোনও অবিস্মরণীয় ফলাফলের প্রয়োজন হয় এবং আমি কীভাবে এটি সমাধান করেছি তা এখানে। এটি ডারিন দিমিত্রভের আপডেট হওয়া সমাধানটির একটি পরিবর্তন।

public static object GetAttributeValue<TAttribute, TValue>(this object val, Func<TAttribute, TValue> valueSelector) where TAttribute : Attribute
{
    try
    {
        Type t = val.GetType();
        TAttribute attr;
        if (t.IsEnum && t.GetField(val.ToString()).GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() is TAttribute att)
        {
            // Applies to Enum values
            attr = att;
        }
        else if (val is PropertyInfo pi && pi.GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() is TAttribute piAtt)
        {
            // Applies to Properties in a Class
            attr = piAtt;
        }
        else
        {
            // Applies to classes
            attr = (TAttribute)t.GetCustomAttributes(typeof(TAttribute), false).FirstOrDefault();
        }
        return valueSelector(attr);
    }
    catch
    {
        return null;
    }
}

ব্যবহারের উদাহরণ:

// Class
SettingsEnum.SettingGroup settingGroup = (SettingsEnum.SettingGroup)(this.GetAttributeValue((SettingGroupAttribute attr) => attr.Value) as SettingsEnum.SettingGroup?);

// Enum
DescriptionAttribute desc = settingGroup.GetAttributeValue((DescriptionAttribute attr) => attr) as DescriptionAttribute;

// PropertyInfo       
foreach (PropertyInfo pi in this.GetType().GetProperties())
{
    string setting = ((SettingsEnum.SettingName)(pi.GetAttributeValue((SettingNameAttribute attr) => attr.Value) as SettingsEnum.SettingName?)).ToString();
}

0

তারপরে প্রচুর কোড লিখুন, কেবল এটি করুন:

{         
   dynamic tableNameAttribute = typeof(T).CustomAttributes.FirstOrDefault().ToString();
   dynamic tableName = tableNameAttribute.Substring(tableNameAttribute.LastIndexOf('.'), tableNameAttribute.LastIndexOf('\\'));    
}

0

যখন আপনার একই নামের সাথে ওভাররাইড পদ্ধতি রয়েছে তখন নীচের সহায়কটি ব্যবহার করুন

public static TValue GetControllerMethodAttributeValue<T, TT, TAttribute, TValue>(this T type, Expression<Func<T, TT>> exp, Func<TAttribute, TValue> valueSelector) where TAttribute : Attribute
        {
            var memberExpression = exp?.Body as MethodCallExpression;

            if (memberExpression.Method.GetCustomAttributes(typeof(TAttribute), false).FirstOrDefault() is TAttribute attr && valueSelector != null)
            {
                return valueSelector(attr);
            }

            return default(TValue);
        }

ব্যবহার: var someController = নতুন কিছু নিয়ন্ত্রণকারী (কিছু প্যারাম); var str = typof (SomeController) .GetControllerMethodAttributeValue (x => someController.SomeMethod (It.IsAny ()), (রুটঅ্যাট্রিবিউট রুটঅ্যাট্রিবিউট) => রুটঅ্যাট্রিবিউট.টেম্পলেট);

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.