Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 还有一个问题是如何减少C语言中的代码重复#_C#_Generics_Salesforce_Refactoring_Traits - Fatal编程技术网

C# 还有一个问题是如何减少C语言中的代码重复#

C# 还有一个问题是如何减少C语言中的代码重复#,c#,generics,salesforce,refactoring,traits,C#,Generics,Salesforce,Refactoring,Traits,我有两个对象,我们称它们为A和B 每个都包含以下属性: [IgnoreDataMember] public string SalesforceId { get; set; } 然后我有另外两个对象,让我们称它们为UpdatedA和UpdatedB,它们分别扩展了A和B,只包括: [DataMember(Name = "sf__Id")] public new string SalesforceId { get;

我有两个对象,我们称它们为A和B

每个都包含以下属性:

        [IgnoreDataMember]
        public string SalesforceId { get; set; }
然后我有另外两个对象,让我们称它们为UpdatedA和UpdatedB,它们分别扩展了A和B,只包括:

        [DataMember(Name = "sf__Id")]
        public new string SalesforceId { get; set; }
        [DataMember(Name = "sf__Created")]
        public bool SalesforceCreated { get; set; }
这样做的原因是,我可以使用
ServiceStack
将A和B转换为CSV文件,然后再次使用它将CSV文件从Salesforce转换回C#对象(如果我不忽略
SalesforceId
,上传到Salesforce批量API 2.0将失败)

所以,这个问题的第一个问题是,我真的需要为UpdatedA和UpdatedB创建两个单独的类吗,因为这些类几乎相同,实际上都是恶作剧,因为我只在以下两种方法中使用它们:

        private Dictionary<string, A> Update(Dictionary<string, A> aByExternalIds, RelayerContext context) {
            IConfiguration config = context.Config;
            string url = $"{config["SalesforceInstanceBaseUrl"]}/services/data/{config["SalesforceVersion"]}/jobs/ingest/{context.job.Id}/successfulResults";
            
            this.restClient.Get(url, context.token)
                .FromCsv<List<UploadedA>>()
                .ForEach((updatedA) => {
                    if (aByExternalIds.TryGetValue(updatedA.ExternalId, out A oldA)) {
                        oldA.SalesforceId = updatedA.SalesforceId;
                    }
                });

            return aByExternalIds;
        }

        private Dictionary<string, B> Update(Dictionary<string, B> bBySalesforceAId, RelayerContext context) {
            IConfiguration config = context.Config;
            string url = $"{config["SalesforceInstanceBaseUrl"]}/services/data/{config["SalesforceVersion"]}/jobs/ingest/{context.job.Id}/successfulResults";

            this.restClient.Get(url, context.token)
                .FromCsv<List<UploadedB>>()
                .ForEach((updatedB) => {
                    if (bBySalesforceAId.TryGetValue(updatedB.A__c, out B oldB)) {
                        oldB.SalesforceId = updatedB.SalesforceId;
                    }
                });

            return bBySalesforceAId;
        }
它可以用来返回
updatedA.ExternalId
updatedB.A\u c

但是如果我使用泛型,我不确定方法签名会是什么样子。 另外,如果我不知道如何以通用方式处理
fromcvs()
fromcvs()
(可能传递函数?)

总之,我想做的是将这两种方法简化为一种,如果我能删除一个或两个上传的类,那就更好了


有什么想法吗?

像这样的想法怎么样:

public interface IBase
{
    string SalesforceId { get; set; }
}
public class A : IBase
{
    public string SalesforceId { get; set; }
}
public class UploadedA : A
{
    public new string SalesforceId { 
        get => base.SalesforceId;
        set => base.SalesforceId = value; }
    public bool SalesforceCreated { get; set; }
}

public static void Update<T, TU>(Dictionary<string, T> oldBySalesForceId, Func<TU, string> updatedId)
        where TU : T
        where T : IBase
{
    // Call service and read csv to produce a list of uploaded objects...
    // Substituting with an empty list in the example
    var list = new List<TU>();
    foreach (var updated in list)
    {
        if (oldBySalesForceId.TryGetValue(updatedId(updated), out var old))
        {
            old.SalesforceId = updated.SalesforceId;
        }
    }
}
公共接口IBase
{
字符串SalesforceId{get;set;}
}
公共A类:IBase
{
公共字符串SalesforceId{get;set;}
}
公共类上载A:A
{
公共新字符串SalesforceId{
get=>base.SalesforceId;
set=>base.SalesforceId=value;}
public bool SalesforceCreated{get;set;}
}
公共静态无效更新(字典oldBySalesForceId,Func updateId)
图:T在哪里
T:IBase在哪里
{
//调用服务并读取csv以生成上载对象的列表。。。
//在示例中用空列表替换
var list=新列表();
foreach(列表中更新的var)
{
if(oldBySalesForceId.TryGetValue(updateId(updated),out var old))
{
old.SalesforceId=updated.SalesforceId;
}
}
}
我删除了一些与示例不相关的细节。这使用带有约束的泛型和接口来确保更新的和旧的值都具有SalesForceId

我更改了派生类,使其使用与基类相同的SalesforceId。如果愿意,您可以将其更改为virtual/override,但基类和派生类都具有相同名称的独立属性可能不是一个好主意,因为这样会造成混淆


它使用委托来描述UpdatedA/UpdatedB的id/key。如果愿意,您可以使用接口。

看起来很有希望。我会在周一上班的时候试一试,在我得到更好的答案之前接受它是否有效。:-)我似乎缺少了一个基本要素(对于一个更有经验的C#程序员来说,这可能是显而易见的):我应该如何从我的代码中邀请新方法,包括任何必要的类型参数此.Update(/*参数在此*/)`
public interface IBase
{
    string SalesforceId { get; set; }
}
public class A : IBase
{
    public string SalesforceId { get; set; }
}
public class UploadedA : A
{
    public new string SalesforceId { 
        get => base.SalesforceId;
        set => base.SalesforceId = value; }
    public bool SalesforceCreated { get; set; }
}

public static void Update<T, TU>(Dictionary<string, T> oldBySalesForceId, Func<TU, string> updatedId)
        where TU : T
        where T : IBase
{
    // Call service and read csv to produce a list of uploaded objects...
    // Substituting with an empty list in the example
    var list = new List<TU>();
    foreach (var updated in list)
    {
        if (oldBySalesForceId.TryGetValue(updatedId(updated), out var old))
        {
            old.SalesforceId = updated.SalesforceId;
        }
    }
}