Vra

Kom ons sê ek het 'n klas met die naam Toets met een eiendom genoem titel met 'n persoonlike kenmerk:

public class Test
{
    [DatabaseField("title")]
    public string Title { get; set; }
}

En 'n uitbreiding metode genoem DbField. Ek wonder of kry 'n persoonlike kenmerk van 'n voorwerp byvoorbeeld is selfs moontlik in c #.

Test t = new Test();
string fieldName = t.Title.DbField();
//fieldName will equal "title", the same name passed into the attribute above

Kan dit gedoen word?

Was dit nuttig?

Oplossing

Hier is 'n benadering. Die uitbreiding metode werk, maar dit is nie heeltemal so maklik nie. Ek skep 'n uitdrukking en dan haal die persoonlike kenmerk.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace ConsoleApplication1
{
    public class DatabaseFieldAttribute : Attribute
    {
        public string Name { get; set; }

        public DatabaseFieldAttribute(string name)
        {
            this.Name = name;
        }
    }

    public static class MyClassExtensions
    {
        public static string DbField<T>(this T obj, Expression<Func<T, string>> value)
        {
            var memberExpression = value.Body as MemberExpression;
            var attr = memberExpression.Member.GetCustomAttributes(typeof(DatabaseFieldAttribute), true);
            return ((DatabaseFieldAttribute)attr[0]).Name;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var p = new Program();
            Console.WriteLine("DbField = '{0}'", p.DbField(v => v.Title));

        }
        [DatabaseField("title")]
        public string Title { get; set; }

    }
}

Ander wenke

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Test t = new Test();

            Console.WriteLine(t.FieldName("Title").FieldName<DatabaseFieldAttribute>());
            Console.WriteLine(t.FieldName("Title").FieldIsPrimaryKey<DatabaseFieldAttribute>());
        }


    }

    public class Test
    {
        [DatabaseField("titlezzz", true)]
        public string Title
        {
            get;
            set;
        }
    }


    public class BaseDatabaseFieldAttribute : Attribute
    {
        private readonly string _name;

        public string Name { get { return _name; } }

        public BaseDatabaseFieldAttribute(string name)
        {
            _name = name;
        }
    }
    public class DatabaseFieldAttribute : BaseDatabaseFieldAttribute
    {
        private readonly bool _isPrimaryKey;

        public bool IsPrimaryKey { get { return _isPrimaryKey; } }

        public DatabaseFieldAttribute(string name, bool isPrimaryKey): base(name)
        {
            _isPrimaryKey = isPrimaryKey;
        }
    }

    public static class Helper
    {

        public static PropertyInfo FieldName(this object obj, string propertyName)
        {
            return obj.GetType().GetProperty(propertyName);
        }

        public static string FieldName<T>(this PropertyInfo property) where T: BaseDatabaseFieldAttribute
        {
            object[] os = property.GetCustomAttributes(typeof(T), false);

            if (os != null && os.Length >= 1)
                return (os[0] as T).Name;
            else
                return "N/A";
        }

        public static bool? FieldIsPrimaryKey<T>(this PropertyInfo property) where T : DatabaseFieldAttribute
        {
            object[] os = property.GetCustomAttributes(typeof(T), false);

            if (os != null && os.Length >= 1)
                return (os[0] as T).IsPrimaryKey;
            else
                return null;
        }
    }


}

Dit is, maar uiteindelik is dit gaan 'n ompad wees, want jy sal die Type byvoorbeeld van 'n beroep GetType op jou geval dat die eiendom ontbloot werk op daardie (meer dikwels as nie) te kry, en dan.

In hierdie spesifieke geval, jou uitbreiding metode is nie van plan om in staat wees om die kenmerk inligting te kry, want al wat jy is verby om dit is 'n string.

Uiteindelik, wat jy nodig het, is iets om die PropertyInfo kry vir die eiendom van. Ander antwoorde verwys na die Type, wat hulle nie is, dit is nie die enigste manier om die kenmerk inligting by die PropertyInfo wat jy wil te kry.

Jy kan dit doen deur 'n Type byvoorbeeld met 'n string, vermoedelik, met die naam eiendom, so jy GetProperty op die Type kan noem.

Nog 'n manier om dit te doen sedert C # 3,0 is 'n metode wat 'n Expression<T> neem en gebruik dan die dele van die Expression by die PropertyInfo te kry nie. In hierdie geval, sal jy 'n Expression<Func<string>> of iets te neem waar TResult is string.

As jy die PropertyInfo, jy kan GetCustomAttributes op dit, en kyk noem vir jou kenmerk.

Die voordeel om die uitdrukking benadering is dat Expression<T> afgelei van LambdaExpression, wat jy Compile kan 'n beroep op, en dan bel om die werklike waarde kry, as jy dit nodig het.

As as al daarop gewys, is dit nie moontlik met die sintaksis van die oorspronklike plakkaat beskryf, omdat jy 'n verwysing na PropertyInfo binne die uitbreiding metode nie kan kry. Wat van iets soos hierdie:

// Extension method
public static string GetDbField(this object obj, string propertyName)
{
    PropertyInfo prop = obj.GetType().GetProperty(propertyName);
    object[] dbFieldAtts = prop.GetCustomAttributes(typeof(DatabaseFieldAttribute), true);

    if (dbFieldAtts != null && dbFieldAtts.Length > 0)
    {
        return ((DatabaseFieldAttribute)dbFieldAtts[0]).Name;
    }

    return "UNDEFINED";
}

Jy kan dan kry die info so eenvoudig as:

Test t = new Test();
string dbField = t.GetDbField("Title");

Nee, dit is nie moontlik nie. Die rede hiervoor is dat dit die waarde en nie die eiendom self wat in enige persoonlike uitbreiding metode wat hierdie inligting sal haal sal gestuur word. Sodra jy in daardie uitbreiding metode, is daar geen betroubare manier om terug te spoor om die eiendom self.

Dit mag dalk moontlik wees vir enum waardes , maar so ver as eienskappe op POCO se dit gaan nie werk.

Met die oog op die kenmerk waarde kry, jy die tipe wat die kenmerk is van toepassing op nodig. Jou uitbreiding metode is net om 'n string waarde (die waarde van titel), sodat jy nie in staat sou wees om die werklike geval kry wat die string vandaan kom, en sodat jy kan die oorspronklike tipe nie kan kry wat die eiendom titel behoort aan. Dit maak dit onmoontlik om die kenmerk waarde van jou uitbreiding metode kry.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top