Merge pull request #7141 from RoosterDragon/sync-less-tostring
Generate sync reports faster
This commit is contained in:
@@ -17,7 +17,7 @@ using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Network
|
||||
{
|
||||
using NamesValuesPair = Pair<string[], string[]>;
|
||||
using NamesValuesPair = Pair<string[], object[]>;
|
||||
|
||||
class SyncReport
|
||||
{
|
||||
@@ -35,10 +35,10 @@ namespace OpenRA.Network
|
||||
TypeInfo typeInfo;
|
||||
lock (typeInfoCache)
|
||||
typeInfo = typeInfoCache[type];
|
||||
var values = new string[typeInfo.Names.Length];
|
||||
var values = new object[typeInfo.Names.Length];
|
||||
var index = 0;
|
||||
|
||||
foreach (var func in typeInfo.MemberToStringFunctions)
|
||||
foreach (var func in typeInfo.SerializableCopyOfMemberFunctions)
|
||||
values[index++] = func(sync);
|
||||
|
||||
return Pair.New(typeInfo.Names, values);
|
||||
@@ -166,7 +166,7 @@ namespace OpenRA.Network
|
||||
static ParameterExpression syncParam = Expression.Parameter(typeof(ISync), "sync");
|
||||
static ConstantExpression nullString = Expression.Constant(null, typeof(string));
|
||||
|
||||
public readonly Func<ISync, string>[] MemberToStringFunctions;
|
||||
public readonly Func<ISync, object>[] SerializableCopyOfMemberFunctions;
|
||||
public readonly string[] Names;
|
||||
|
||||
public TypeInfo(Type type)
|
||||
@@ -182,14 +182,25 @@ namespace OpenRA.Network
|
||||
"Invalid Property: " + prop.DeclaringType.FullName + "." + prop.Name);
|
||||
|
||||
var sync = Expression.Convert(syncParam, type);
|
||||
MemberToStringFunctions = fields
|
||||
.Select(fi => MemberToString(Expression.Field(sync, fi), fi.FieldType, fi.Name))
|
||||
.Concat(properties.Select(pi => MemberToString(Expression.Property(sync, pi), pi.PropertyType, pi.Name)))
|
||||
SerializableCopyOfMemberFunctions = fields
|
||||
.Select(fi => SerializableCopyOfMember(Expression.Field(sync, fi), fi.FieldType, fi.Name))
|
||||
.Concat(properties.Select(pi => SerializableCopyOfMember(Expression.Property(sync, pi), pi.PropertyType, pi.Name)))
|
||||
.ToArray();
|
||||
|
||||
Names = fields.Select(fi => fi.Name).Concat(properties.Select(pi => pi.Name)).ToArray();
|
||||
}
|
||||
|
||||
static Func<ISync, object> SerializableCopyOfMember(MemberExpression getMember, Type memberType, string name)
|
||||
{
|
||||
if (memberType.IsValueType)
|
||||
{
|
||||
// We can get a copy just by accessing the member since it is a value type.
|
||||
var boxedCopy = Expression.Convert(getMember, typeof(object));
|
||||
return Expression.Lambda<Func<ISync, object>>(boxedCopy, name, new[] { syncParam }).Compile();
|
||||
}
|
||||
return MemberToString(getMember, memberType, name);
|
||||
}
|
||||
|
||||
static Func<ISync, string> MemberToString(MemberExpression getMember, Type memberType, string name)
|
||||
{
|
||||
// The lambda generated is shown below.
|
||||
@@ -197,10 +208,13 @@ namespace OpenRA.Network
|
||||
var toString = memberType.GetMethod("ToString", Type.EmptyTypes);
|
||||
Expression getString;
|
||||
if (memberType.IsValueType)
|
||||
{
|
||||
// (ISync sync) => { return ((TSync)sync).Foo.ToString(); }
|
||||
getString = Expression.Call(getMember, toString);
|
||||
}
|
||||
else
|
||||
{
|
||||
// (ISync sync) => { var foo = ((TSync)sync).Foo; return foo == null ? null : foo.ToString()); }
|
||||
// (ISync sync) => { var foo = ((TSync)sync).Foo; return foo == null ? null : foo.ToString(); }
|
||||
var memberVariable = Expression.Variable(memberType, getMember.Member.Name);
|
||||
var assignMemberVariable = Expression.Assign(memberVariable, getMember);
|
||||
var member = Expression.Block(new[] { memberVariable }, assignMemberVariable);
|
||||
|
||||
Reference in New Issue
Block a user