提交 b94cd2ba 编写于 作者: T tanghai

1.将Component中的逻辑代码移动到Controller,这样可以reload这部分代码,实现方式是使用扩展方法,所以调用的方式可以不用改变.

2.本来想让Object支持集合初始化形式,例如 Object obj = new Object {{"a", 1}}.
这样需要继承IEnumerable,并且需要添加一个Add(string key, object value)方法,但是一旦实现IEnumerable接口,Mongdb会使用EnumerableSerializer序列化该类,导致异常.

google到如下说明:

https://jira.mongodb.org/browse/CSHARP-460

Here is a summary of the current situation:
1. Any class that subclasses a .NET collection class ends up being serialized using BsonClassMapSerializer, which doesn't work because the .NET collection class isn't designed the way BsonClassMapSerializer expects
2. As a result, the serialized document contains any public properties added by the derived class but does not contain the collection itself
Item 2 is particularly surprising to people...
The plan is to change the serialization of classes that implement collection interfaces to work better in more cases (but unfortunately not all). The new approach is essentially identical to that taken by the XmlSerializer in .NET.
The new approach will be:
1. Any class that implements IDictionary<TKey, TValue> will be serialized using DictionarySerializer<TKey, TValue>
2. Any class that implements IDictionary will be serialized using DictionarySerializer
2. Any class that implements IEnumerable<T> will be serialized using EnumerableSerializer<T>
3. Any class that implements IEnumerable will be serialized using EnumerableSerializer
Classes that implement IEnumerable<T> will also have to implement ICollection<T> if deserialization is desired (the Add method in ICollection<T> is needed for deserialization).
Classes that implement IEnumerable will also have to implement IList if deserialization is desired (the Add method in IList is needed for deserialization).
NOTE: just like with XmlSerializer, if your custom class implements either IEnumerable or IDictionary (legacy or generic) then ONLY the collection values will be serialized. If your custom class added additional public properties they will NOT be serialized.
This is the opposite behavior as before, but is wrong less often (not serializing the collection values is always wrong, but custom collections that don't have additional properties are now serialized correctly).
If you want to serialize your additional properties along with the collection values you will have to encapsulate and delegate to the collection class instead of subclassing it.
Alex's suggestion to add a KeyValuePairSerializer<TKey, TValue> is a good one also.
Work is in progress on this change.
上级 a808568b
using System;
using System.Collections.Generic;
using Common.Event;
using Model;
using MongoDB.Bson;
namespace Controller
{
/// <summary>
/// 控制复杂的buff逻辑,可以reload
/// </summary>
public static class BuffComponentExtension
{
public static void Add(this BuffComponent buffComponent, Buff buff)
{
if (buffComponent.buffs.Contains(buff))
{
throw new ArgumentException(string.Format("already exist same buff, Id: {0} ConfigId: {1}", buff.Id, buff.Config.Id));
}
if (buffComponent.idBuff.ContainsKey(buff.Id))
{
throw new ArgumentException(string.Format("already exist same buff, Id: {0} ConfigId: {1}", buff.Id, buff.Config.Id));
}
Env env = new Env();
env[EnvKey.Unit] = buffComponent.Owner;
env[EnvKey.Buff] = buff;
World.Instance.GetComponent<EventComponent<WorldEventAttribute>>().Trigger(WorldEventType.BeforeAddBuff, env);
buffComponent.buffs.Add(buff);
buffComponent.idBuff.Add(buff.Id, buff);
buffComponent.typeBuff.Add(buff.Config.Type, buff);
World.Instance.GetComponent<EventComponent<WorldEventAttribute>>().Trigger(WorldEventType.AfterAddBuff, env);
}
public static Buff GetById(this BuffComponent buffComponent, ObjectId id)
{
if (!buffComponent.idBuff.ContainsKey(id))
{
return null;
}
return buffComponent.idBuff[id];
}
public static Buff GetOneByType(this BuffComponent buffComponent, BuffType type)
{
return buffComponent.typeBuff.GetOne(type);
}
public static Buff[] GetByType(this BuffComponent buffComponent, BuffType type)
{
return buffComponent.typeBuff.GetByKey(type);
}
private static bool Remove(this BuffComponent buffComponent, Buff buff)
{
if (buff == null)
{
return false;
}
Env env = new Env();
env[EnvKey.Unit] = buffComponent.Owner;
env[EnvKey.Buff] = buff;
World.Instance.GetComponent<EventComponent<UnitEventAttribute>>().Trigger(WorldEventType.BeforeRemoveBuff, env);
buffComponent.buffs.Remove(buff);
buffComponent.idBuff.Remove(buff.Id);
buffComponent.typeBuff.Remove(buff.Config.Type, buff);
World.Instance.GetComponent<EventComponent<UnitEventAttribute>>().Trigger(WorldEventType.AfterRemoveBuff, env);
return true;
}
public static bool RemoveById(this BuffComponent buffComponent, ObjectId id)
{
Buff buff = buffComponent.GetById(id);
return buffComponent.Remove(buff);
}
public static void RemoveByType(this BuffComponent buffComponent, BuffType type)
{
Buff[] allbuffs = buffComponent.GetByType(type);
foreach (Buff buff in allbuffs)
{
buffComponent.Remove(buff);
}
}
}
}
\ No newline at end of file
namespace Controller
{
/// <summary>
/// 控制复杂的buff逻辑,可以reload
/// </summary>
public class BuffController
{
}
}
\ No newline at end of file
......@@ -48,13 +48,16 @@
<Compile Include="BehaviorTreeNode\Not.cs" />
<Compile Include="BehaviorTreeNode\Selector.cs" />
<Compile Include="BehaviorTreeNode\Sequence.cs" />
<Compile Include="BuffController.cs" />
<Compile Include="EnvKey.cs" />
<Compile Include="UnitComponentExtension.cs" />
<Compile Include="BuffComponentExtension.cs" />
<Compile Include="ConfigCategory\BuffCategory.cs" />
<Compile Include="ConfigCategory\GlobalCategory.cs" />
<Compile Include="ConfigCategory\NodeCategory.cs" />
<Compile Include="ConfigCategory\UnitCategory.cs" />
<Compile Include="NodeType.cs" />
<Compile Include="Factory\UnitFactory.cs" />
<Compile Include="WorldEventType.cs" />
<Compile Include="UnitType.cs" />
</ItemGroup>
<ItemGroup>
......
namespace Controller
{
public static class EnvKey
{
public const string Unit = "Unit";
public const string Buff = "Buff";
}
}
......@@ -9,6 +9,9 @@ namespace Controller
{
Unit player = new Unit(configId);
player.AddComponent<BuffComponent>();
Buff buff = new Buff(1);
player.GetComponent<BuffComponent>().Add(buff);
World.Instance.GetComponent<UnitComponent>().Add(player);
return player;
}
}
......
using System;
using System.Collections.Generic;
using System.Linq;
using Model;
using MongoDB.Bson;
namespace Controller
{
/// <summary>
/// 控制复杂的unit逻辑,可以reload
/// </summary>
public static class UnitComponentExtension
{
public static void Add(this UnitComponent unitComponent, Unit unit)
{
unitComponent.units.Add(unit.Id, unit);
if (!unitComponent.typeUnits.ContainsKey(unit.Config.Type))
{
unitComponent.typeUnits.Add(unit.Config.Type, new Dictionary<ObjectId, Unit>());
}
unitComponent.typeUnits[unit.Config.Type].Add(unit.Id, unit);
}
public static Unit Get(this UnitComponent unitComponent, ObjectId id)
{
Unit unit = null;
unitComponent.units.TryGetValue(id, out unit);
return unit;
}
public static Unit[] GetOneType(this UnitComponent unitComponent, int type)
{
Dictionary<ObjectId, Unit> oneTypeUnits = null;
if (!unitComponent.typeUnits.TryGetValue(type, out oneTypeUnits))
{
return new Unit[0];
}
return oneTypeUnits.Values.ToArray();
}
public static bool Remove(this UnitComponent unitComponent, Unit unit)
{
if (unit == null)
{
throw new ArgumentNullException("unit");
}
if (!unitComponent.units.Remove(unit.Id))
{
return false;
}
if (!unitComponent.typeUnits[unit.Config.Type].Remove(unit.Id))
{
return false;
}
return true;
}
public static bool Remove(this UnitComponent unitComponent, ObjectId id)
{
Unit unit = unitComponent.Get(id);
if (unit == null)
{
return false;
}
return unitComponent.Remove(unit);
}
}
}
\ No newline at end of file
namespace Controller
{
public static class WorldEventType
{
public const int BeforeAddBuff = 0;
public const int AfterAddBuff = 1;
public const int BeforeRemoveBuff = 2;
public const int AfterRemoveBuff = 3;
}
}
......@@ -4,7 +4,7 @@ using Common.Base;
namespace Model
{
public class BehaviorTreeComponent: Component<World>
public class BehaviorTreeComponent : Component<World>, IAssemblyLoader
{
private Dictionary<int, BehaviorTree> trees = new Dictionary<int, BehaviorTree>();
......
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using Common.Base;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
......@@ -9,11 +8,13 @@ namespace Model
public class BuffComponent: Component<Unit>
{
[BsonElement]
private HashSet<Buff> buffs;
public HashSet<Buff> buffs;
private Dictionary<ObjectId, Buff> idBuff;
[BsonIgnore]
public Dictionary<ObjectId, Buff> idBuff;
private MultiMap<BuffType, Buff> typeBuff;
[BsonIgnore]
public MultiMap<BuffType, Buff> typeBuff;
public BuffComponent()
{
......@@ -41,71 +42,5 @@ namespace Model
this.typeBuff.Add(buff.Config.Type, buff);
}
}
public void Add(Buff buff)
{
if (this.buffs.Contains(buff))
{
throw new ArgumentException(string.Format("already exist same buff, Id: {0} ConfigId: {1}", buff.Id, buff.Config.Id));
}
if (this.idBuff.ContainsKey(buff.Id))
{
throw new ArgumentException(string.Format("already exist same buff, Id: {0} ConfigId: {1}", buff.Id, buff.Config.Id));
}
this.buffs.Add(buff);
this.idBuff.Add(buff.Id, buff);
this.typeBuff.Add(buff.Config.Type, buff);
}
public Buff GetById(ObjectId id)
{
if (!this.idBuff.ContainsKey(id))
{
return null;
}
return this.idBuff[id];
}
public Buff GetOneByType(BuffType type)
{
return this.typeBuff.GetOne(type);
}
public Buff[] GetByType(BuffType type)
{
return this.typeBuff.GetByKey(type);
}
private bool Remove(Buff buff)
{
if (buff == null)
{
return false;
}
this.buffs.Remove(buff);
this.idBuff.Remove(buff.Id);
this.typeBuff.Remove(buff.Config.Type, buff);
return true;
}
public bool RemoveById(ObjectId id)
{
Buff buff = this.GetById(id);
return this.Remove(buff);
}
public void RemoveByType(BuffType type)
{
Buff[] allbuffs = this.GetByType(type);
foreach (Buff buff in allbuffs)
{
this.Remove(buff);
}
}
}
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ using Common.Config;
namespace Model
{
public class ConfigComponent: Component<World>
public class ConfigComponent : Component<World>, IAssemblyLoader
{
public Dictionary<Type, ICategory> allConfig;
......
......@@ -6,7 +6,8 @@ using Common.Event;
namespace Model
{
public class EventComponent<T>: Component<World> where T : AEventAttribute
public class EventComponent<AttributeType> : Component<World>, IAssemblyLoader
where AttributeType : AEventAttribute
{
private Dictionary<int, List<IEvent>> events;
......@@ -17,7 +18,7 @@ namespace Model
var types = assembly.GetTypes();
foreach (var t in types)
{
object[] attrs = t.GetCustomAttributes(typeof (T), false);
object[] attrs = t.GetCustomAttributes(typeof (AttributeType), false);
if (attrs.Length == 0)
{
continue;
......
......@@ -5,7 +5,7 @@ using Common.Base;
namespace Model
{
public class FactoryComponent<T>: Component<World> where T : Entity<T>
public class FactoryComponent<T> : Component<World>, IAssemblyLoader where T : Entity<T>
{
private Dictionary<int, IFactory<T>> allConfig;
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using Common.Base;
using MongoDB.Bson;
......@@ -8,64 +6,10 @@ namespace Model
{
public class UnitComponent: Component<World>
{
private readonly Dictionary<ObjectId, Unit> units =
public readonly Dictionary<ObjectId, Unit> units =
new Dictionary<ObjectId, Unit>();
private readonly Dictionary<int, Dictionary<ObjectId, Unit>> typeUnits =
public readonly Dictionary<int, Dictionary<ObjectId, Unit>> typeUnits =
new Dictionary<int, Dictionary<ObjectId, Unit>>();
public void Add(Unit unit)
{
this.units.Add(unit.Id, unit);
if (!this.typeUnits.ContainsKey(unit.Config.Type))
{
this.typeUnits.Add(unit.Config.Type, new Dictionary<ObjectId, Unit>());
}
this.typeUnits[unit.Config.Type].Add(unit.Id, unit);
}
public Unit Get(ObjectId id)
{
Unit unit = null;
this.units.TryGetValue(id, out unit);
return unit;
}
public Unit[] GetOneType(int type)
{
Dictionary<ObjectId, Unit> oneTypeUnits = null;
if (!this.typeUnits.TryGetValue(type, out oneTypeUnits))
{
return new Unit[0];
}
return oneTypeUnits.Values.ToArray();
}
public bool Remove(Unit unit)
{
if (unit == null)
{
throw new ArgumentNullException("unit");
}
if (!this.units.Remove(unit.Id))
{
return false;
}
if (!this.typeUnits[unit.Config.Type].Remove(unit.Id))
{
return false;
}
return true;
}
public bool Remove(ObjectId id)
{
Unit unit = this.Get(id);
if (unit == null)
{
return false;
}
return this.Remove(unit);
}
}
}
\ No newline at end of file
using System.Reflection;
namespace Model
{
public interface IAssemblyLoader
{
void Load(Assembly assembly);
}
}
......@@ -59,6 +59,7 @@
<Compile Include="Config\BuffConfig.cs" />
<Compile Include="FactoryAttribute.cs" />
<Compile Include="Component\FactoryComponent.cs" />
<Compile Include="IAssemblyLoader.cs" />
<Compile Include="IFactory.cs" />
<Compile Include="Component\UnitComponent.cs" />
<Compile Include="BuffType.cs" />
......@@ -67,6 +68,8 @@
<Compile Include="Config\NodeConfig.cs" />
<Compile Include="Unit.cs" />
<Compile Include="World.cs" />
<Compile Include="UnitEventAttribute.cs" />
<Compile Include="WorldEventAttribute.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
......
using Common.Event;
namespace Model
{
public class UnitEventAttribute: AEventAttribute
{
public UnitEventAttribute(int type): base(type)
{
}
}
}
namespace Model
using System.IO;
using System.Reflection;
using Common.Base;
namespace Model
{
public class World : GameObject<World>
{
private static readonly World instance = new World();
public Assembly Assembly { get; set; }
public static World Instance
{
get
......@@ -14,6 +20,22 @@
private World()
{
this.Assembly = Assembly.Load(File.ReadAllBytes(@"./Controller.dll"));
}
public void ReLoad()
{
this.Assembly = Assembly.Load(File.ReadAllBytes(@"./Controller.dll"));
foreach (Component<World> component in this.GetComponents())
{
IAssemblyLoader assemblyLoader = component as IAssemblyLoader;
if (assemblyLoader == null)
{
continue;
}
assemblyLoader.Load(this.Assembly);
}
}
}
}
\ No newline at end of file
using Common.Event;
namespace Model
{
public class WorldEventAttribute: AEventAttribute
{
public WorldEventAttribute(int type): base(type)
{
}
}
}
using System;
using System.IO;
using System.Reflection;
using Common.Helper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Model;
......@@ -23,21 +21,23 @@ namespace MongoDBTest
World world = World.Instance;
Assembly assembly = Assembly.Load(File.ReadAllBytes(@"./Controller.dll"));
// 加载配置
world.AddComponent<ConfigComponent>().Load(assembly);
world.AddComponent<ConfigComponent>().Load(world.Assembly);
// 事件管理器
world.AddComponent<EventComponent<WorldEventAttribute>>().Load(world.Assembly);
world.AddComponent<UnitComponent>();
// 构造工厂
world.AddComponent<FactoryComponent<Unit>>().Load(assembly);
world.AddComponent<FactoryComponent<Unit>>().Load(world.Assembly);
// 构造行为树
world.AddComponent<BehaviorTreeComponent>().Load(assembly);
world.AddComponent<BehaviorTreeComponent>().Load(world.Assembly);
Unit player1 = world.GetComponent<FactoryComponent<Unit>>().Create(1);
Buff buff = new Buff(1);
player1.GetComponent<BuffComponent>().Add(buff);
player1["hp"] = 10;
collection.Insert(player1);
......
......@@ -69,10 +69,6 @@
<Project>{19F8F043-1F99-4550-99DF-DEA5C7D77E55}</Project>
<Name>Common</Name>
</ProjectReference>
<ProjectReference Include="..\Controller\Controller.csproj">
<Project>{e69c1f22-e004-4d69-8667-787bd243454b}</Project>
<Name>Controller</Name>
</ProjectReference>
<ProjectReference Include="..\Model\Model.csproj">
<Project>{0fa529d1-d0a9-4a8e-90f5-117ce80f2ede}</Project>
<Name>Model</Name>
......
......@@ -57,9 +57,7 @@ namespace Common.Base
Component<K> t;
if (!this.componentDict.TryGetValue(typeof (T), out t))
{
throw new Exception(
string.Format("GetComponent, component not exist, id: {0}, component: {1}",
this.Id, typeof(T).Name));
return default (T);
}
return (T) t;
}
......
using System.Collections.Generic;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
......@@ -72,7 +73,7 @@ namespace Common.Base
this.values[typeof (T).Name] = obj;
}
public bool Contain(string key)
public bool ContainKey(string key)
{
return this.values.ContainsKey(key);
}
......@@ -87,6 +88,20 @@ namespace Common.Base
return ret;
}
public void Add(string key, object value)
{
if (this.values == null)
{
this.values = new Dictionary<string, object>();
}
this.values.Add(key, value);
}
public IEnumerator GetEnumerator()
{
return this.values.GetEnumerator();
}
public virtual void BeginInit()
{
if (this.values == null)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册