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().GetPro开发者_StackOverflow社区perties(); //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.
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);
}
}
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.
精彩评论