简体   繁体   中英

In C#, if I have generic objects, how can I generically specify getting and setting fields on those objects?

I have two very similiar functions:

        public Dictionary<string, T> UpdateSuccessProperties<T, TU>(Dictionary<string, T> oldSObjectByAlternativeIds, List<TU> updatedSObjects)
        where TU : T
        where T : AlternativeIdentifiable {
            updatedSObjects.ForEach((updatedSObject) => {
                    if (oldSObjectByAlternativeIds.TryGetValue(updatedSObject.GetAlternativeId(), out T oldSObject)) {
                        oldSObject.SalesforceId = updatedSObject.SalesforceId;
                    }
                });

            return oldSObjectByAlternativeIds;
        }
        public Dictionary<string, T> UpdateFailureProperties<T, TU>(Dictionary<string, T> oldSObjectByAlternativeIds, List<TU> updatedSObjects)
        where TU : T
        where T : AlternativeIdentifiable {
            updatedSObjects.ForEach((updatedSObject) => {
                    if (oldSObjectByAlternativeIds.TryGetValue(updatedSObject.GetAlternativeId(), out T oldSObject)) {
                        oldSObject.SalesforceError = updatedSObject.SalesforceError;
                    }
                });

            return oldSObjectByAlternativeIds;
        }

It will be noticed there are only 3 differences other than the method name:

  • The very end of the url
  • The property on oldSObject of type T which will receive a new value.
  • The property on updatedSObject of type TU which will supply the old value.

Is there some way I can consolidate these into something like this (pseudocode, doesn't work):

        public Dictionary<string, T> UpdateProperties<T, TU>(Dictionary<string, T> oldSObjectByAlternativeIds, List<TU> updatedSObjects, string receiverField, string supplierField)
        where TU : T
        where T : AlternativeIdentifiable {
            updatedSObjects.ForEach((updatedSObject) => {
                    if (oldSObjectByAlternativeIds.TryGetValue(updatedSObject.GetAlternativeId(), out T oldSObject)) {
                        oldSObject.set(receiverField, updatedSObject.get(supplierField));
                    }
                });

            return oldSObjectByAlternativeIds;
        }

?

The last two parameters needn't be strings; I'd actually prefer something typesafe.

Why not use Action<T, TU> , which could be: (oldSObject, updatedSObject) => oldSObject.SalesforceError = updatedSObject.SalesforceError :

public Dictionary<string, T> UpdateFailureProperties<T, TU>(Dictionary<string, T> oldSObjectByAlternativeIds, List<TU> updatedSObjects, Action<T, TU> callback)
    where TU : T
    where T : AlternativeIdentifiable
{
    updatedSObjects.Get(url, context.token)
        .FromCsv<List<TU>>()
        .ForEach((updatedSObject) =>
        {
            if (oldSObjectByAlternativeIds.TryGetValue(updatedSObject.GetAlternativeId(), out T oldSObject))
            {
                callback(oldSObject, updatedSObject);
            }
        });

    return oldSObjectByAlternativeIds;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM