通过扩展方法更新值而不返回

本文关键字:返回 更新 扩展 方法 | 更新日期: 2023-09-27 18:06:40

现在我这样使用;

c1 = c1.AddItem(d1);
public static T AddItem<T, TItem>(this T entity, TItem item) where T : BaseClass<T>
{
    //somecode
    return entity; 
}

但是我想能够改变值而不返回;

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;
        }
    }

通过扩展方法更新值而不返回

您的问题似乎是由这一行引起的:

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的调用将返回一个与传入的对象实例不同的引用。

这具有级联效果,在您的扩展方法中,局部变量entity被重新分配给一个全新的对象。因为entity引用变量是c1引用变量的副本(而不是对它的引用),所以当它被重新分配时,更改不会反映在c1变量中。您的c1变量有效地仍然指向原始的entity实例,在被调用BaseClass.Load()更改之前。

基本上,正如其他人已经说过的,要编写一个不需要返回entity引用的扩展方法,您必须限制自己通过entity对象的方法/属性更改状态。实际上,你不能完全改变对象引用,因为这永远不会在方法调用之外反映出来。

在您的情况下,看起来您应该坚持使用返回entity引用的原始扩展方法。


相关阅读:c#中的参数传递

,特别是,旁注:按引用传递值对象和按值传递引用对象之间的区别是什么?适用于这里发生的事情

字符串是不可变的,与其他类类型你的代码应该工作。

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);
}