维拓标准接口开发项目总结

引言

维拓标准接口的开发也基本完成了,这也是我首次用 C# 完成定制项目。之前 Unity 学的很多东西都忘掉了,再捡起来用还是有些吃力,所以写了这篇博客总结一下。

C#程序配置与 <bindingRedirect/>

在完成部分接口把程序打包成exe时重新校对了一下 NewtonJson 的版本,之前在 Nuget 上下载的是 13 版本,但是 GStarCAD 目录下的版本是 12。将版本调整之后 exe 无法正常使用:

未经处理的异常:SystemI0.Fi1eLoadException:未能加载文件或程序集“Newtonsoft.Json,Version=13.0.0.0 Culture=neutral Pub1icKeyToken=30ad4fe6b2a6aeed”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。(异常来自 HRESULT:0x80131040)--->SystemIO.Fi1eLoadException:未能加载文件或程序集“Newtonsoft.Ison,Version=12.0.0.0,Culture=neutral, PublicKe yToken=30ad4fe6b2a6aeed”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。(异常来自 HRESULT:0x80131040)

再次检查 Nuget 版本已经调整过来了,但是编译之后的 exe 还是会报错 NewtonJson 版本错误。其实只需要调整一下 app.config 文件:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

问题在于 <bindingRedirect/> 这个标签,微软官方API文档 这里有比较详细的解释。

将一个程序集版本重定向到另一个版本。

<bindingRedirect
oldVersion="existing assembly version"
newVersion="new assembly version"/>
  • oldVersion:指定最初请求的程序集的版本。 程序集版本号的格式为 major.minor.build.revision。 该版本号的每个部分的有效值介于 0 和 65535 之间。
  • newVersion:指定要用来取代最初请求的版本的程序集版本(格式为:n.n.n.n) ,此值可以指定 oldVersion 之前的版本。

官方还给出了一个示例演示如何将一个程序集版本重定向到另一个版本:

<configuration>  
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="myAssembly"
publicKeyToken="32ab4ba45e0a69a1"
culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0"
newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

所以把这个标签删掉,程序就可以正常运行了,这是一个知识盲点记录下来。

PLM接口使用

NewtonSoftJson自定义Convertor序列化Json

这个项目一个比较关键的过程就是去解析图纸数据并转换为 Json 格式,前面 PLM 接口负责解析数据,那么该如何将这些数据转换为 Json 呢?

查阅官网的 Custom JsonConverter,给出了一个比较完整的示例:

public class KeysJsonConverter : JsonConverter
{
private readonly Type[] _types;

public KeysJsonConverter(params Type[] types)
{
_types = types;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);

if (t.Type != JTokenType.Object)
{
t.WriteTo(writer);
}
else
{
JObject o = (JObject)t;
IList<string> propertyNames = o.Properties().Select(p => p.Name).ToList();

o.AddFirst(new JProperty("Keys", new JArray(propertyNames)));

o.WriteTo(writer);
}
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
}

public override bool CanRead
{
get { return false; }
}

public override bool CanConvert(Type objectType)
{
return _types.Any(t => t == objectType);
}
}

public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public IList<string> Roles { get; set; }
}
Employee employee = new Employee
{
FirstName = "James",
LastName = "Newton-King",
Roles = new List<string>
{
"Admin"
}
};

string json = JsonConvert.SerializeObject(employee, Formatting.Indented, new KeysJsonConverter(typeof(Employee)));

Console.WriteLine(json);
// {
// "Keys": [
// "FirstName",
// "LastName",
// "Roles"
// ],
// "FirstName": "James",
// "LastName": "Newton-King",
// "Roles": [
// "Admin"
// ]
// }

Employee newEmployee = JsonConvert.DeserializeObject<Employee>(json, new KeysJsonConverter(typeof(Employee)));

Console.WriteLine(newEmployee.FirstName);
// James

UML类图绘制