在没有 return 的情况下通过扩展方法更新值
updating value by extension method without return
现在我是这样用的;
c1 = c1.AddItem(d1);
public static T AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
//somecode
return entity;
}
但我希望能够在没有 return;
的情况下更改值
c1.AddItem(d1);
public static void AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
//somecode
}
知道如何让它工作吗?
完整代码
public class C : BaseClass<C>
{
public virtual int CId { get; set; }
public virtual string Text { get; set; }
public virtual IList<D> DList { get; set; }
public C()
{
DList = new List<D>();
}
}
public static T AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
var propertyList = item.GetType().GetProperties().ToList();
var prop = propertyList.Find(c => c.PropertyType == typeof(T));
if (propertyList.Any(c => c.PropertyType == typeof(T)))
{
propertyList.Find(c => c.PropertyType == typeof(T)).SetValue(item, entity);
}
else
{
((IList<T>)propertyList.Find(c => c.PropertyType == typeof(IList<T>)).GetValue(item)).Add(entity);
}
var a = ((IList<TItem>)entity.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(entity));
if (a.GetType().Name == "PersistentGenericBag`1")
{
entity = entity.Load(x => (IList<TItem>)x.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(x));
a = ((IList<TItem>)entity.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(entity));
}
a.Add(item);
entity.Save();
return entity;
}
public static T Load<T, TItem>(this T entity, Func<T, IList<TItem>> listGetter) where T : class
{
using (var session = NHibernateHelper<T>.OpenSession())
{
T reAttached = session.Merge<T>(entity);
NHibernate.NHibernateUtil.Initialize(listGetter.Invoke(reAttached));
return reAttached;
}
}
字符串是不可变的,对于其他 class 类型,您的代码应该可以工作。
public class BaseClass<TItem>
{
public BaseClass()
{
ItemList = new List<TItem>();
}
public List<TItem> ItemList { get; set; }
}
public static void AddItem<T, TItem>(this T entity, TItem item)
where T :BaseClass<TItem>
{
//somecode
entity.ItemList.Add(item);
}
public class TItem
{
public string Name { get; set; }
}
static void Main(string[] args)
{
BaseClass<TItem> myEntity = new BaseClass<TItem>();
TItem newItem = new TItem();
newItem.Name = "Hi";
myEntity.AddItem(newItem);
}
您的问题似乎是由以下行引起的:
entity = entity.Load(x => (IList<TItem>)x.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(x));
现在您已经发布了 Load
方法的内容,我们可以看到它依次调用:
T reAttached = session.Merge<T>(entity);
// ...
return reAttached;
我对 Hibernate 的了解有限,但很有可能,即使并非总是如此,但至少有时,对 Merge
的调用将 return 引用与当前对象实例不同的对象实例已通过。
这具有级联效应,在您的扩展方法中,局部变量 entity
被重新分配给一个全新的对象。因为 entity
引用变量是 c1
引用变量的 copy (而不是对它的引用),所以当它被重新分配时,更改不会反映出来在 c1
变量中。您的 c1
变量实际上仍然指向原始 entity
实例 ,在 它被调用 BaseClass.Load()
.
更改之前
基本上,正如其他人已经指出的那样,要编写不需要 return entity
引用的扩展方法,您必须限制自己更改 entity
对象的状态 通过它的 methods/properties。您实际上不能完全更改对象引用,因为这永远不会反映在方法调用之外。
在您的情况下,您似乎应该坚持使用 return 作为 entity
参考的原始扩展方法。
特别是旁注:按引用传递值对象和按值传递引用对象有什么区别?适用于此处发生的情况。
现在我是这样用的;
c1 = c1.AddItem(d1);
public static T AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
//somecode
return entity;
}
但我希望能够在没有 return;
的情况下更改值c1.AddItem(d1);
public static void AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
//somecode
}
知道如何让它工作吗?
完整代码
public class C : BaseClass<C>
{
public virtual int CId { get; set; }
public virtual string Text { get; set; }
public virtual IList<D> DList { get; set; }
public C()
{
DList = new List<D>();
}
}
public static T AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
var propertyList = item.GetType().GetProperties().ToList();
var prop = propertyList.Find(c => c.PropertyType == typeof(T));
if (propertyList.Any(c => c.PropertyType == typeof(T)))
{
propertyList.Find(c => c.PropertyType == typeof(T)).SetValue(item, entity);
}
else
{
((IList<T>)propertyList.Find(c => c.PropertyType == typeof(IList<T>)).GetValue(item)).Add(entity);
}
var a = ((IList<TItem>)entity.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(entity));
if (a.GetType().Name == "PersistentGenericBag`1")
{
entity = entity.Load(x => (IList<TItem>)x.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(x));
a = ((IList<TItem>)entity.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(entity));
}
a.Add(item);
entity.Save();
return entity;
}
public static T Load<T, TItem>(this T entity, Func<T, IList<TItem>> listGetter) where T : class
{
using (var session = NHibernateHelper<T>.OpenSession())
{
T reAttached = session.Merge<T>(entity);
NHibernate.NHibernateUtil.Initialize(listGetter.Invoke(reAttached));
return reAttached;
}
}
字符串是不可变的,对于其他 class 类型,您的代码应该可以工作。
public class BaseClass<TItem>
{
public BaseClass()
{
ItemList = new List<TItem>();
}
public List<TItem> ItemList { get; set; }
}
public static void AddItem<T, TItem>(this T entity, TItem item)
where T :BaseClass<TItem>
{
//somecode
entity.ItemList.Add(item);
}
public class TItem
{
public string Name { get; set; }
}
static void Main(string[] args)
{
BaseClass<TItem> myEntity = new BaseClass<TItem>();
TItem newItem = new TItem();
newItem.Name = "Hi";
myEntity.AddItem(newItem);
}
您的问题似乎是由以下行引起的:
entity = entity.Load(x => (IList<TItem>)x.GetType().GetProperties().ToList().Find(c => c.PropertyType == typeof(IList<TItem>)).GetValue(x));
现在您已经发布了 Load
方法的内容,我们可以看到它依次调用:
T reAttached = session.Merge<T>(entity);
// ...
return reAttached;
我对 Hibernate 的了解有限,但很有可能,即使并非总是如此,但至少有时,对 Merge
的调用将 return 引用与当前对象实例不同的对象实例已通过。
这具有级联效应,在您的扩展方法中,局部变量 entity
被重新分配给一个全新的对象。因为 entity
引用变量是 c1
引用变量的 copy (而不是对它的引用),所以当它被重新分配时,更改不会反映出来在 c1
变量中。您的 c1
变量实际上仍然指向原始 entity
实例 ,在 它被调用 BaseClass.Load()
.
基本上,正如其他人已经指出的那样,要编写不需要 return entity
引用的扩展方法,您必须限制自己更改 entity
对象的状态 通过它的 methods/properties。您实际上不能完全更改对象引用,因为这永远不会反映在方法调用之外。
在您的情况下,您似乎应该坚持使用 return 作为 entity
参考的原始扩展方法。
特别是旁注:按引用传递值对象和按值传递引用对象有什么区别?适用于此处发生的情况。