public void LookupGetAndSet() { var get = AccessorCache <Person> .LookupGet(p => p.Name, out var prop); Assert.AreEqual("Name", prop); var set = AccessorCache <Person> .LookupSet(p => p.Name, out prop); Assert.AreEqual("Name", prop); var person = new Person { Name = "tanaka" }; get(person).Is("tanaka"); set(person, "kimura"); person.Name.Is("kimura"); }
public bool SetPropertyPathValue(object?value) { if (Source == null) { return(false); } if (Next != null) { return(Next.SetPropertyPathValue(value)); } else { var setter = _setAccessor ?? (_setAccessor = AccessorCache.LookupSet(Source.GetType(), PropertyName)); setter.DynamicInvoke(Source, value); return(true); } }
/// <summary> /// Data binding method. /// </summary> /// <typeparam name="TView">View type</typeparam> /// <typeparam name="TProperty">Property type</typeparam> /// <param name="self">View</param> /// <param name="propertySelector">Target property selector</param> /// <param name="source">Source property</param> /// <returns>Data binding token</returns> public static IDisposable SetBinding <TView, TProperty>( this TView self, Expression <Func <TView, TProperty> > propertySelector, ReadOnlyReactiveProperty <TProperty> source) where TView : View { var d = new CompositeDisposable(); bool isUpdating = false; string propertyName; var setter = AccessorCache <TView> .LookupSet(propertySelector, out propertyName); source .Where(_ => !isUpdating) .Subscribe(x => setter(self, x)) .AddTo(d); return(d); }
private static IObservable <TProperty> ObserveSimpleProperty <TSubject, TProperty>( this TSubject subject, Expression <Func <TSubject, TProperty> > propertySelector, bool isPushCurrentValueAtFirst = true) where TSubject : INotifyPropertyChanged { var isFirst = true; var accessor = AccessorCache <TSubject> .LookupGet(propertySelector, out var propertyName); return(Observable.Defer(() => { var flag = isFirst; isFirst = false; var q = subject.PropertyChangedAsObservable() .Where(e => e.PropertyName == propertyName || string.IsNullOrEmpty(e.PropertyName)) .Select(_ => accessor.Invoke(subject)); return (isPushCurrentValueAtFirst && flag) ? q.StartWith(accessor.Invoke(subject)) : q; })); }
private static IDisposable CreateOneWayBinding <T, TTarget, TProperty>(IObservable <T> self, TTarget target, Expression <Func <TTarget, TProperty> > propertySelector, Func <T, TProperty> convert, TProperty propertyFallbackValue) { var propertyName = default(string); return(self .Subscribe(value => { var setter = AccessorCache <TTarget> .LookupSet(propertySelector, out propertyName); try { setter(target, convert(value)); } catch (Exception ex) { Debug.WriteLine(ex); setter(target, propertyFallbackValue); } })); }
/// <summary>Update by object's PropertyName.</summary> /// <param name="tableName">Target database's table.</param> /// <param name="updateItem">Table's column name extracted from PropertyName.</param> /// <param name="whereCondition">Where condition extracted from PropertyName.</param> /// <returns>Rows affected.</returns> public int Update(string tableName, object updateItem, object whereCondition) { Contract.Requires <ArgumentException>(!String.IsNullOrEmpty(tableName)); Contract.Requires <ArgumentNullException>(whereCondition != null); Contract.Requires <ArgumentNullException>(updateItem != null); var update = string.Join(", ", AccessorCache.Lookup(updateItem.GetType()) .Where(p => p.IsReadable) .Select(p => p.Name + " = " + parameterSymbol + p.Name)); var where = string.Join(" and ", AccessorCache.Lookup(whereCondition.GetType()) .Select(p => p.Name + " = " + parameterSymbol + "__extra__" + p.Name)); var query = string.Format("update {0} set {1} where {2}", tableName, update, where); Contract.Assume(query.Length > 0); using (var command = PrepareExecute(query, CommandType.Text, updateItem, whereCondition)) { return(command.ExecuteNonQuery()); } }
public void StructTest() { var accessors = AccessorCache.Lookup(typeof(TestMockStruct)) .OrderBy(x => x.Name) .ToArray(); accessors.Length.Is(10); accessors.All(a => a.DeclaringType == typeof(TestMockStruct)); accessors.Take(8).All(a => a.IsReadable); accessors.Take(8).All(a => a.IsWritable); accessors.Select(a => a.Name).Is("Field1", "Field2", "Property1", "Property2", "Property3", "Property4", "Property5", "Property6", "PropertyReadOnly", "PropertySetOnly"); object target = new TestMockStruct(); accessors[0].SetValue(target, "a"); accessors[2].SetValue(target, "b"); accessors[4].SetValue(target, "c"); accessors[6].IsWritable.Is(false); accessors[1].SetValue(target, 1); accessors[3].SetValue(target, 2); accessors[5].SetValue(target, 3); accessors[7].IsWritable.Is(false); accessors.Where(a => a.IsReadable).Select(a => a.GetValue(target)) .Is("a", 1, "b", 2, null, 0, null); Enumerable.Repeat((TestMockStruct)target, 1) .SelectMany(m => new object[] { m.Field1, m.Field2, m.Property1, m.Property2, m.Property5, m.Property6 }) .Is("a", 1, "b", 2, null, 0); var read = accessors[8]; read.IsReadable.Is(true); read.IsWritable.Is(false); var write = accessors[9]; write.IsReadable.Is(false); write.IsWritable.Is(true); write.SetValue(target, "test"); Assert.AreEqual("test", ((TestMockStruct)target).AsDynamic().hiddenField); }
/// <summary> /// InsertAndGetするためのパラメーターを生成します。 /// </summary> /// <typeparam name="T">テーブルにマッピングされた型</typeparam> /// <param name="data">挿入するデータ</param> /// <returns>パラメーター</returns> private Tuple <DbCommand, DbParameter> CreateInsertAndGetParameter <T>(T data) { //--- command var factory = DbProvider.GetFactory(this.DbKind); dynamic command = factory.CreateCommand(); command.BindByName = true; command.Connection = (dynamic)this.Connection; if (this.Timeout.HasValue) { command.CommandTimeout = this.Timeout.Value; } //--- parameters DbParameter output = null; foreach (var x in TableMappingInfo.Create <T>().Columns) { dynamic parameter = factory.CreateParameter(); parameter.ParameterName = x.PropertyName; parameter.DbType = x.ColumnType; if (x.IsPrimaryKey) { parameter.Direction = ParameterDirection.Output; output = parameter; command.CommandText = $@"{PrimitiveSql.CreateInsert<T>(this.DbKind)} returning {x.ColumnName} into :{x.PropertyName}"; } else { parameter.Direction = ParameterDirection.Input; parameter.Value = AccessorCache <T> .LookupGet(x.PropertyName)(data); } command.Parameters.Add(parameter); } //--- ok return(Tuple.Create((DbCommand)command, output)); }
/// <summary> /// バルク方式での挿入処理の準備を行います。 /// </summary> /// <typeparam name="T">テーブルにマッピングされた型</typeparam> /// <param name="executor">バルク処理実行機能</param> /// <param name="data">挿入する生データ</param> /// <returns>挿入するデータ</returns> private DataTable SetupBulkInsert <T>(SqlBulkCopy executor, IEnumerable <T> data) { //--- タイムアウト if (this.Timeout.HasValue) { executor.BulkCopyTimeout = this.Timeout.Value; } //--- 対象テーブル名 var info = TableMappingInfo.Create <T>(); executor.DestinationTableName = info.FullName; //--- 列のマップ var table = new DataTable(); var getters = new List <Func <T, object> >(); foreach (var x in info.Columns) { executor.ColumnMappings.Add(x.PropertyName, x.ColumnName); table.Columns.Add(new DataColumn { ColumnName = x.PropertyName, DataType = x.IsNullable ? Nullable.GetUnderlyingType(x.PropertyType) : x.PropertyType, AllowDBNull = x.IsNullable }); getters.Add(AccessorCache <T> .LookupGet(x.PropertyName)); } //--- データ生成 foreach (var x in data) { var row = table.NewRow(); for (int i = 0; i < getters.Count; i++) { row[i] = getters[i](x); } table.Rows.Add(row); } return(table); }
private static IDisposable CreateOneWayToSourceBinding <T, TTarget, TProperty>(IReactiveProperty <T> self, TTarget target, Expression <Func <TTarget, TProperty> > propertySelector, Func <TProperty, T> convertBack, IObservable <Unit> targetUpdateTrigger, T sourceFallbackValue) { var propertyName = default(string); if (targetUpdateTrigger == null) { throw new NotSupportedException("OneWayToSource binding required targetUpdateTrigger parameter."); } return(targetUpdateTrigger .Subscribe(_ => { try { self.Value = convertBack(AccessorCache <TTarget> .LookupGet(propertySelector, out propertyName)(target)); } catch (Exception ex) { Debug.WriteLine(ex); self.Value = sourceFallbackValue; } })); }
/// <summary> /// Data binding method. /// </summary> /// <typeparam name="TView">View type</typeparam> /// <typeparam name="TProperty">Property type</typeparam> /// <param name="self">View</param> /// <param name="propertySelector">Target property selector</param> /// <param name="source">Source property</param> /// <param name="updateSourceTrigger">Update source trigger</param> /// <returns>Data binding token</returns> public static IDisposable SetBinding <TView, TProperty>( this TView self, Expression <Func <TView, TProperty> > propertySelector, ReactiveProperty <TProperty> source, Func <TView, IObservable <Unit> > updateSourceTrigger = null) where TView : UIBarItem { var d = new CompositeDisposable(); bool isUpdating = false; string propertyName; var setter = AccessorCache <TView> .LookupSet(propertySelector, out propertyName); source .Where(_ => !isUpdating) .Subscribe(x => setter(self, x)) .AddTo(d); if (updateSourceTrigger != null) { var getter = AccessorCache <TView> .LookupGet(propertySelector, out propertyName); updateSourceTrigger(self).Subscribe(_ => { isUpdating = true; try { source.Value = getter(self); } finally { isUpdating = false; } }).AddTo(d); } return(d); }
public static IEnumerable <dynamic> OrderBy <T>(IEnumerable <dynamic> source, string property, bool isDescending) { return(isDescending ? source.OrderByDescending(AccessorCache.GetAccessor <dynamic>(property)) : source.OrderBy(AccessorCache.GetAccessor <dynamic>(property))); }
public static IDisposable OneWayBind <TType, TProperty>(this TType type, Expression <Func <TType, Action <TProperty> > > selector, IObservable <TProperty> observable) { return(observable.ObserveOnUIDispatcher() .Subscribe(x => { AccessorCache <TType> .LookupMethod(selector).Invoke(type).Invoke(x); })); }
public AccessorCacheTests(ITestOutputHelper output) { this.output = output; AccessorCache <Person> .Clear(); }
public static IOrderedEnumerable <dynamic> ThenByDescending(this IOrderedEnumerable <dynamic> source, string property) { return(Enumerable.ThenByDescending <dynamic, object>(source, AccessorCache.GetAccessor(property), Comparer <object> .Default)); }
public static IOrderedEnumerable <dynamic> OrderBy(this IEnumerable <dynamic> source, string property) { return(Enumerable.OrderBy <dynamic, object>(source, AccessorCache.GetAccessor(property), Comparer <object> .Default)); }
public static Func <dynamic, object> PropertyAccessor(dynamic source, string property) { return(AccessorCache.GetAccessor(property)); }
public static object PropertyValue(dynamic source, string property) { return(AccessorCache.GetAccessor(property)(source)); }
public IRuleBuilderInitial <T, TType> RuleForProp <TType>(Expression <Func <T, ValidatableProperty <TType> > > expression) { var propName = expression.Body.ToString().Split(new char[] { '.' })[1]; var param = Expression.Parameter(typeof(T), "a"); var navigationProperty = typeof(T).GetRuntimeProperty(propName); var name = typeof(ValidatableProperty <TType>).GetRuntimeProperty("Value"); var navigationPropertyAccess = Expression.MakeMemberAccess(param, navigationProperty); var nameAccess = Expression.MakeMemberAccess(navigationPropertyAccess, name); var lambdaAccess = Expression.Lambda <Func <T, TType> >(nameAccess, new List <ParameterExpression>() { param }); var member = lambdaAccess.GetMember(); var compiled = member == null || ValidatorOptions.DisableAccessorCache ? lambdaAccess.Compile() : AccessorCache <T> .GetCachedAccessor(member, lambdaAccess); var rule = new PropertyRule(member, compiled.CoerceToNonGeneric(), lambdaAccess, () => CascadeMode.Continue, typeof(TType), typeof(T)); AddRule(rule); IRuleBuilderOptions <T, TType> ruleBuilder = new RuleBuilder <T, TType>(rule); ruleBuilder = ruleBuilder.WithName(propName); return((IRuleBuilderInitial <T, TType>)ruleBuilder); }
/// <summary> /// When using the ValidatableProperty type, use this method to avoid needing to supply the ".Value" /// which is needed when using RuleForProp. /// </summary> /// <typeparam name="TType"></typeparam> /// <param name="expression"></param> /// <returns></returns> public IRuleBuilderInitial <T, TType> RuleForProp <TType>(Expression <Func <T, ValidatableProperty <TType> > > expression, CascadeMode cascadeMode = CascadeMode.Continue) { var lambdaExpression = (MemberExpression)expression.Body; var propName = lambdaExpression.Member.Name; var originalPropertyType = typeof(T).GetRuntimeProperty(propName); var actualPropertyToValidate = typeof(ValidatableProperty <TType>).GetRuntimeProperty("Value"); var generatedExpression = Expression.Parameter(typeof(T), "a"); var navigationPropertyAccess = Expression.MakeMemberAccess(generatedExpression, originalPropertyType); var lambdaNameMemberAccess = Expression.MakeMemberAccess(navigationPropertyAccess, actualPropertyToValidate); var lambdaAccess = Expression.Lambda <Func <T, TType> >(lambdaNameMemberAccess, new List <ParameterExpression>() { generatedExpression }); var generatedMember = lambdaAccess.GetMember(); var compiled = generatedMember == null || ValidatorOptions.DisableAccessorCache ? lambdaAccess.Compile() : AccessorCache <T> .GetCachedAccessor(generatedMember, lambdaAccess); var rule = new PropertyRule(generatedMember, compiled.CoerceToNonGeneric(), lambdaAccess, () => cascadeMode, typeof(TType), typeof(T)); AddRule(rule); IRuleBuilderOptions <T, TType> ruleBuilder = new RuleBuilder <T, TType>(rule, this); ruleBuilder = ruleBuilder.WithName(propName); return((IRuleBuilderInitial <T, TType>)ruleBuilder); }
/// <summary>If connection is not open then open and create command.</summary> /// <param name="query">SQL code.</param> /// <param name="commandType">Command Type.</param> /// <param name="parameter">PropertyName parameterized to PropertyName. if null then no use parameter.</param> /// <param name="extraParameter">CommandName set to __extra__PropertyName.</param> /// <returns>Setuped IDbCommand.</returns> protected IDbCommand PrepareExecute(string query, CommandType commandType, object parameter, object extraParameter = null) { Contract.Requires <ArgumentException>(!String.IsNullOrEmpty(query)); Contract.Ensures(Contract.Result <IDbCommand>() != null); if (connection.State != ConnectionState.Open) { connection.Open(); } if (transaction == null && isUseTransaction) { transaction = connection.BeginTransaction(isolationLevel); } var command = connection.CreateCommand(); command.CommandText = query; command.CommandType = commandType; if (parameter != null) { foreach (var p in AccessorCache.Lookup(parameter.GetType())) { if (!p.IsReadable) { continue; } Contract.Assume(parameter != null); if (p.GetValueDirect(parameter) is IDataParameter) { command.Parameters.Add(p.GetValueDirect(parameter)); } else { var param = command.CreateParameter(); param.ParameterName = p.Name; param.Value = p.GetValueDirect(parameter); command.Parameters.Add(param); } } } if (extraParameter != null) { foreach (var p in AccessorCache.Lookup(extraParameter.GetType())) { if (!p.IsReadable) { continue; } Contract.Assume(extraParameter != null); var param = command.CreateParameter(); param.ParameterName = "__extra__" + p.Name; param.Value = p.GetValueDirect(extraParameter); command.Parameters.Add(param); } } if (transaction != null) { command.Transaction = transaction; } return(command); }