I don't think there is anything built in; however, you can probably
automate much of the work - the following makes a fairly crude (but very
quick) shallow-copy using the default .ctor() [making a point of
ignoring the primary key field(s) - although it isn't really
LINQ-specific] - with the advantage that since this is an extension
method, you could replace on an individual basis by adding a specific
Clone() method to the partial class, and it will be
chosen by the compiler.
using System;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
Foo foo = new Foo { Id = 16, Name = "Fred", DoB = DateTime.Today };
Foo bar = foo.Clone();
}
}
class Foo
{
[Column(IsPrimaryKey = true)] // PK
public int Id { get; set; }
[Column] // test with non-PK ColumnAttribute
public string Name { get; set; }
// test w/o ColumnAttribute
public DateTime DoB { get; set; }
}
public static class ObjectExt
{
public static T Clone<T>(this T obj) where T : new()
{
return ObjectExtCache<T>.Clone(obj);
}
static class ObjectExtCache<T> where T : new()
{
private static readonly Func<T, T> cloner;
static ObjectExtCache()
{
ParameterExpression param = Expression.Parameter(typeof(T),
"in");
var bindings = from prop in typeof(T).GetProperties()
where prop.CanRead && prop.CanWrite
let column = Attribute.GetCustomAttribute(prop,
typeof(ColumnAttribute))
as ColumnAttribute
where column == null || !column.IsPrimaryKey
select (MemberBinding)Expression.Bind(prop,
Expression.Property(param, prop));
cloner = Expression.Lambda<Func<T,T>>(
Expression.MemberInit(
Expression.New(typeof(T)), bindings), param).Compile();
}
public static T Clone(T obj)
{
return cloner(obj);
}
}
}