在没有 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 参考的原始扩展方法。


相关阅读:Parameter passing in C#

特别是旁注:按引用传递值对象和按值传递引用对象有什么区别?适用于此处发生的情况。