简体   繁体   中英

Property set method not found

When this line bckPk = Translate(packs); executes I am getting Property set method not found. error which is pretty natural. But can someone suggest me a workaround for this by which I can achieve what I am trying to do here?

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Reflection;

namespace ExperimentProjects
{
    public class ClassOne
    {
        public string PropertyOne { get; set; }
        public string PropertyTwo { get; set; }
        public string PropertyThree { get; set; }
    }
    public class ClassTwo
    {
        public string PropertyOne { get; set; }
        public string PropertyTwo { get; set; }
        public string PropertyThree { get; set; }

    }

    public class ClassPack : Collection<ClassOne>
    {

    }

    public class ClassBckPack : Collection<ClassOne>
    {

    }
    public class TranslateClass
    {
        public static TResult Translate<TSource, TResult>(TSource sourceObj)
        {

            Type typeOfSourceObj = sourceObj.GetType();
            Type typeOfResultObj = typeof(TResult);
            if (typeOfSourceObj.BaseType.Equals(typeOfResultObj.BaseType))
            {
                //Console.WriteLine("1");

            }

            ConstructorInfo constructorOfresultObj = typeOfResultObj.GetConstructor(System.Type.EmptyTypes);
            Object[] parameters = new Object[0];
            TResult result = (TResult)constructorOfresultObj.Invoke(parameters);
            PropertyInfo[] propertiesInSourceObj = typeOfSourceObj.GetProperties();
            if (propertiesInSourceObj.Length != 0)
            {
                foreach (PropertyInfo property in propertiesInSourceObj)
                {
                    Console.WriteLine(property.PropertyType.Name);
                    PropertyInfo propertyOfResultObj = typeOfResultObj.GetProperty(property.Name);

                    if (propertyOfResultObj != null)
                    {
                        propertyOfResultObj.SetValue(result, property.GetValue(sourceObj));
                    }
                }
            }

            Console.Read();
            return result;
        }
        static void Main(string[] args)
        {
            ClassOne objOne = new ClassOne();
            objOne.PropertyOne = "One";
            objOne.PropertyTwo = "Two";
            objOne.PropertyThree = "Three";
            ClassTwo objTwo = Translate<ClassOne, ClassTwo>(objOne);
            Console.WriteLine(objTwo.PropertyOne + " " + objTwo.PropertyTwo + " " + objTwo.PropertyThree);
            ClassOne o = Translate<ClassOne, ClassOne>(objOne);
            Console.WriteLine(o.PropertyOne + " " + o.PropertyTwo + " " + o.PropertyThree);
            ClassPack packs = new ClassPack();
            packs.Add(o);
            packs.Add(objOne);

            ClassBckPack bckPk = null;
            try
            {
                bckPk = Translate<ClassPack, ClassBckPack>(packs);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.Read();
            }
            foreach (ClassOne eachObj in bckPk)
                Console.WriteLine(eachObj.PropertyOne + " " + eachObj.PropertyTwo + " " + eachObj.PropertyThree);
            Console.Read();
        }
    }
}

EDIT : Here I want to copy the object from packs to bckPk using Reflection, not using a foreach loop. For example take this following example :

Class Content
{

}

Class AContents : Collection<Content>
{
}

Class BContents : Collection<Content>
{
}

Class BusinessEntity
{
    public AContents
    {
      get; set;
    }
}
Class DataContract
{
    public AContents
    {
     get; set;
    }
}

I want to use this Translate method this way now :

BusinessEntity be= new BusinessEntity ();
DataContract dc= new DataContract ();

dc=Translate<BusinessEntity,DataContract>(be);

If I run this code then will throw Property set method not found error

You are getting the exception because you are trying to set a value to the ReadOnly property. ie, a property defined only with getter.

here you forgot about inheritence since your class is inheriting from base Collection<T> class you are getting the exception

As you are trying to read all the properties in ClassPack and set in ClassBckPack , they have inherited member called Count which is readonly that means it doesn't define the Set method. So you are getting the above exception.

Please read the following API from System.Collections.ObjectModel

 public class Collection<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
    // Summary:
    //     Initializes a new instance of the System.Collections.ObjectModel.Collection<T>
    //     class that is empty.
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    public Collection();
    //
    // Summary:
    //     Initializes a new instance of the System.Collections.ObjectModel.Collection<T>
    //     class as a wrapper for the specified list.
    //
    // Parameters:
    //   list:
    //     The list that is wrapped by the new collection.
    //
    // Exceptions:
    //   System.ArgumentNullException:
    //     list is null.
    public Collection(IList<T> list);

    // Summary:
    //     Gets the number of elements actually contained in the System.Collections.ObjectModel.Collection<T>.
    //
    // Returns:
    //     The number of elements actually contained in the                           ****System.Collections.ObjectModel.Collection<T>.
    public int Count { get; }****
    //
    // Summary:
    //     Gets a System.Collections.Generic.IList<T> wrapper around the System.Collections.ObjectModel.Collection<T>.
    //
    // Returns:
    //     A System.Collections.Generic.IList<T> wrapper around the System.Collections.ObjectModel.Collection<T>.
    protected IList<T> Items { get; }

So here is the work around

Create your CustomAttribute say "ExampleAttribute" and apply only to those Properties which you are trying to update from source class to target class. Then Read all the properties check whether the property is typeof your new attribute. Thats how you will diffrentiate Properties of base class from your child class.

 foreach (PropertyInfo propertyInfo in type.GetProperties())
        {
            object[] attrObjs = propertyInfo.GetCustomAttributes(typeof(ExampleAttribute), true);
            if (attrObjs.Length > 0)
            {
             }
         }

I feel this make sense. thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM