简体   繁体   中英

Extending (inherit) entity framwork class (not using partial)

How it started?

I wanted to add two columns, that are not in business objec collection into radGridView. Specifically NewUrl anad NewIdOnFilehost. :)

So what i tried to do?

I put this into grid

radGridViewReuploadStatus.ItemsSource = FileHostings.Filesonic.getdAllDeletedLinks();

Then i added them new columns

<telerik:GridViewColumn Header="New F.H.Id" UniqueName="NewFilehostId" Width="*"></telerik:GridViewColumn>
                <telerik:GridViewColumn Header="New URL" UniqueName="NewUrl" Width="*"></telerik:GridViewColumn>

So what is problem?

radGridViewReuploadStatus.Rows does not exists. I don't know why they did not added it to wpf radGridView, it is in its aspx version. I was able to get rows using getChildsOfType, but this is obviously not ideal way.

What i did next?

class dlExtended : DownloadLink {
        public string NewUrl { get; set; }
        public string NewIdOnFilehost { get; set; }
    }

Finally the PROBLEM - what basic i don't understand

How do i make dlExtended from DownloadLink? (i know it is wrong name convention, it is just for example:) ) And how do i make list of dlExtended from collection of DownloadLink? There must be better way then using foreach!

Now i'm probably doing it wrong

So now i should do constructor and set EACH property of dlExneded according to one passed in passed DownloadLink?!

Well maybe it is doable by reflection LIKE this

public DownloadLinkExtended(DownloadLink origDl){
        PropertyInfo[] myObjectProperties = origDl.GetType().GetProperties(); //BindingFlags.Public | BindingFlags.NonPublic
        foreach (PropertyInfo pi in myObjectProperties)
        {
            if (pi.GetValue(origDl, null) != null)
            {
                pi.SetValue(this, pi.GetValue(origDl, null), null);
            }
        }
    }

Well this is stupid. So what i don't get about extending the class and adding new properties to it?

I know that EF4 classes are partial and i can add properties to them simply via partial class, but i want these only for the grid and not anywhere else.

If these are EF classes (not POCO from the T4 templates) then you may not want to inherit from them anyway - because you end up with the the EF baggage. That aside I think there are a number of potential solutions.

If its only used in one place, you can improve on the for loop with projection in Linq

var newthings = oldlinks.Select(old => new dlExtended{ NewUrl =old.NewUrl , NewIdOnFilehost =old.NewIdOnFilehost });

you can also write a constructor for dlExtended that takes a DownloadLink and then do

var newthings = oldlinks.Select(old => new dlExtended(old));

which puts the property copying in one place.

you can also build a generic extension method to copy properties with the same name between two objects and use that in a variety of ways.

My "Shallow" object copier is very similar to yours, but the null test is subtly different. It also has a handy extension method wrapper - so it will need to be in a static class.

    /// <summary>
    /// Copy an object to destination object, only matching fields will be copied
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="sourceObject">An object with matching fields of the destination object</param>
    /// <param name="destObject">Destination object, must already be created</param>
    public static void ShallowCopyTo<T>(this object sourceObject, ref T destObject)
    {
        Copy<T>(sourceObject,ref destObject);
    }
    /// <summary>
    /// Copy an object to destination object, only matching fields will be copied
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="sourceObject">An object with matching fields of the destination object</param>
    /// <param name="destObject">Destination object, must already be created</param>
    public static void Copy<T>(object sourceObject, ref T destObject)
    {
        //  If either the source, or destination is null, return
        if (sourceObject == null || destObject == null)
            return;

        //  Get the type of each object
        Type sourceType = sourceObject.GetType();
        Type targetType = destObject.GetType();

        //  Loop through the source properties
        foreach (PropertyInfo p in sourceType.GetProperties())
        {
            //  Get the matching property in the destination object
            PropertyInfo targetObj = targetType.GetProperty(p.Name);
            //  If there is none, skip
            if (targetObj == null)
                continue;

            //  Set the value in the destination
            targetObj.SetValue(destObject, p.GetValue(sourceObject, null), null);
        }
    }

However, I also have a deep copier, but this only works with serializable objects, so look into the code generation you use from the EDMX, I don't think it will work with the EF classes directly, but does with the POCO generated classes.

/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// 
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>

public static class ObjectCopier
{
    /// <summary>
    /// Perform a deep Copy of the object.
    /// </summary>
    /// <typeparam name="T">The type of object being copied.</typeparam>
    /// <param name="source">The object instance to copy.</param>
    /// <returns>The copied object.</returns>
    public static T Clone<T>(this T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }

        // Don't serialize a null object, simply return the default for that object
        if (Object.ReferenceEquals(source, null))
        {
            return default(T);
        }

        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, source);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }

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