public void Can_add_signals() { var type = new NetTypeInfo("test"); var signal = new NetSignalInfo(type, "signalName"); signal.AddParameter(NetVariantType.Bool); type.GetSignal(0).Should().BeNull(); type.SignalCount.Should().Be(0); type.AddSignal(signal); type.SignalCount.Should().Be(1); type.GetSignal(0).Name.Should().Be("signalName"); type.GetSignal(0).GetParameter(0).Should().Be(NetVariantType.Bool); }
public void Can_create_signal_info() { using (var type = new NetTypeInfo("full type name")) using (var signal = new NetSignalInfo(type, "testSignal")) { signal.ParentType.FullTypeName.Should().Be("full type name"); signal.Name.Should().Be("testSignal"); signal.ParameterCount.Should().Be(0); signal.GetParameter(0).Should().Be(NetVariantType.Invalid); signal.AddParameter(NetVariantType.Double); signal.ParameterCount.Should().Be(1); signal.GetParameter(0).Should().Be(NetVariantType.Double); signal.GetParameter(1).Should().Be(NetVariantType.Invalid); } }
public void OnNetTypeInfoCreated(NetTypeInfo netTypeInfo, Type forType) { if (!IsApplicableFor(forType)) { return; } var mvvmTypeInfo = new MvvmTypeInfo(); TypeInfos.Add(forType, mvvmTypeInfo); for (var i = 0; i < netTypeInfo.PropertyCount; i++) { int?existingSignalIndex = null; var property = netTypeInfo.GetProperty(i); if (property.NotifySignal != null) { // In this case some other behavior or the user has already set up a notify signal for this property. // We don't want to destroy that. mvvmTypeInfo.AddPropertyInfo(property.Name, property.NotifySignal.Name); continue; } var signalName = CalculateSignalNameFromPropertyName(property.Name); mvvmTypeInfo.AddPropertyInfo(property.Name, signalName); // Check if this signal already has been registered. for (var signalIndex = 0; signalIndex < netTypeInfo.SignalCount; signalIndex++) { var signal = netTypeInfo.GetSignal(signalIndex); if (string.Equals(signalName, signal.Name)) { existingSignalIndex = signalIndex; break; } } if (existingSignalIndex.HasValue) { // Signal for this property is already existent but not registered (we check that above). property.NotifySignal = netTypeInfo.GetSignal(existingSignalIndex.Value); continue; } // Create a new signal and link it to the property. var notifySignalInfo = new NetSignalInfo(netTypeInfo, signalName); netTypeInfo.AddSignal(notifySignalInfo); property.NotifySignal = notifySignalInfo; } }
public void LoadTypeInfo(IntPtr t) { using (var type = new NetTypeInfo(t)) { var typeInfo = Type.GetType(type.FullTypeName); if (typeInfo == null) { throw new InvalidOperationException($"Invalid type {type.FullTypeName}"); } // Don't grab properties and methods for system-level types. if (Helpers.IsPrimitive(typeInfo)) { return; } if (typeInfo.IsArray) { type.IsArray = true; } else { if (typeof(IList).IsAssignableFrom(typeInfo)) { type.IsList = true; } else if (typeInfo.IsGenericType) { if (typeof(IList <>).IsAssignableFrom(typeInfo.GetGenericTypeDefinition())) { type.IsList = true; } } } if (typeof(IQmlComponentCompleted).IsAssignableFrom(typeInfo)) { type.HasComponentCompleted = true; } if (typeof(IQmlObjectDestroyed).IsAssignableFrom(typeInfo)) { type.HasObjectDestroyed = true; } foreach (var methodInfo in typeInfo.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { if (methodInfo.IsGenericMethod) { continue; // No generics supported. } if (Helpers.IsPrimitive(methodInfo.DeclaringType)) { continue; } if (methodInfo.IsSpecialName) { continue; // Ignore the property get/set methods. } NetTypeInfo returnType = null; if (methodInfo.ReturnParameter != null && methodInfo.ReturnParameter.ParameterType != typeof(void)) { returnType = NetTypeManager.GetTypeInfo(methodInfo.ReturnParameter.ParameterType); } var method = new NetMethodInfo(type, methodInfo.Name, returnType, methodInfo.IsStatic); foreach (var parameter in methodInfo.GetParameters()) { method.AddParameter(parameter.Name, NetTypeManager.GetTypeInfo(parameter.ParameterType)); } type.AddMethod(method); } var signals = new Dictionary <string, NetSignalInfo>(); foreach (var signalAttribute in typeInfo.GetCustomAttributes(false).OfType <SignalAttribute>()) { if (string.IsNullOrEmpty(signalAttribute.Name)) { throw new InvalidOperationException($"Signal name was null for {typeInfo.Name}"); } if (!char.IsLower(signalAttribute.Name[0])) { throw new InvalidOperationException($"Signal {signalAttribute.Name} for {typeInfo.Name} must begin with a lower case letter."); } var signal = new NetSignalInfo(type, signalAttribute.Name); foreach (var parameter in signalAttribute.Parameters) { signal.AddParameter(parameter); } type.AddSignal(signal); signals.Add(signal.Name, signal); } foreach (var propertyInfo in typeInfo.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { if (Helpers.IsPrimitive(propertyInfo.DeclaringType)) { continue; } NetSignalInfo notifySignal = null; var notifySignalAttribute = propertyInfo.GetCustomAttribute <NotifySignalAttribute>(); if (notifySignalAttribute != null) { var name = notifySignalAttribute.Name; if (string.IsNullOrEmpty(name)) { name = $"{propertyInfo.Name}Changed"; name = char.ToLower(name[0]) + name.Substring(1); } if (signals.ContainsKey(name)) { notifySignal = signals[name]; // Make sure the signal we are referencing has no parameters. if (notifySignal.ParameterCount != 0) { // TODO: They can actually of parameters, but not implemented yet. throw new Exception("Notify signals must have no parameters."); } } else { if (!char.IsLower(name[0])) { throw new InvalidOperationException($"Signal {name} for {typeInfo.Name} must begin with a lower case letter."); } notifySignal = new NetSignalInfo(type, name); type.AddSignal(notifySignal); } } using (var property = new NetPropertyInfo( type, propertyInfo.Name, NetTypeManager.GetTypeInfo(propertyInfo.PropertyType), propertyInfo.CanRead, propertyInfo.CanWrite, notifySignal)) { foreach (var indexParameter in propertyInfo.GetIndexParameters()) { property.AddIndexParameter(indexParameter.Name, NetTypeManager.GetTypeInfo(indexParameter.ParameterType)); } type.AddProperty(property); } } // NOTE: This type is going to get a typeInfo object // with IsLoading=true and IsLoaded=false. It technically // is loaded, but it's misleading. InteropBehaviors.OnNetTypeInfoCreated(type, typeInfo); } }