While converting PostSharp.Samples.Xaml sample to use EntityFramework, I am encountering "k__BackingField" problem mentioned in PostSharp inserting k__Backing Field into Entity Class, causing Database generation to fail. Can you show me how to use the proposed solution "Use MulticastAttributeUsageAttribute.AttributeTargets to restrict it to properties." without losing PostSharp's INotifyPropertyChanged? I am trying to persuade the stakeholders by showcasing both EF and PS.
Here's the change to AddressModel.cs
using System;
using System.ComponentModel;
using System.Text;
using PostSharp.Patterns.Contracts;
using PostSharp.Patterns.Model;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace PostSharp.Samples.Xaml
{
public class AddressModel : ModelBase
{
public int AddressId { get; set; }
[DisplayName("Address Line 1")]
[Patterns.Contracts.Required]
public string Line1 { get; set; }
[DisplayName("Address Line 2")]
public string Line2 { get; set; }
[Patterns.Contracts.Required]
public string Town { get; set; }
public string Country { get; set; }
public DateTime Expiration { get; set; }
[IgnoreAutoChangeNotification]
public TimeSpan Lifetime => DateTime.Now - Expiration;
[SafeForDependencyAnalysis]
public string FullAddress
{
get
{
var stringBuilder = new StringBuilder();
if (Line1 != null) stringBuilder.Append(Line1);
if (Line2 != null)
{
if (stringBuilder.Length > 0) stringBuilder.Append("; ");
stringBuilder.Append(Line2);
}
if (Town != null)
{
if (stringBuilder.Length > 0) stringBuilder.Append("; ");
stringBuilder.Append(Town);
}
if (Country != null)
{
if (stringBuilder.Length > 0) stringBuilder.Append("; ");
stringBuilder.Append(Country);
}
return stringBuilder.ToString();
}
}
[ForeignKey("AddressId")]
[Parent]
public virtual CustomerModel Person { get; set; }
}
}
app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="PostSharp" publicKeyToken="b13fd38b8f9c99d7" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.37.0" newVersion="5.0.37.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
CustomerModel.cs
using System.IO;
using System.Threading;
using PostSharp.Patterns.Collections;
using PostSharp.Patterns.Contracts;
using PostSharp.Patterns.Model;
using PostSharp.Patterns.Threading;
using System;
using System.ComponentModel.DataAnnotations;
using PostSharp.Extensibility;
namespace PostSharp.Samples.Xaml
{
public class CustomerModel : ModelBase
{
[Key]
public int CustomerId { get; set; }
public string FirstName { get; set; }
[Patterns.Contracts.Required]
public string LastName { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
[Child]
public AdvisableCollection<AddressModel> Addresses { get; set; }
[Reference]
public AddressModel PrincipalAddress { get; set; }
[Reader]
public void Save(string path)
{
using (var stringWriter = new StreamWriter(path))
{
// We need to make sure the object graph is not being modified when we save,
// and this is ensured by [ReaderWriterSynchronized] in ModelBase.
stringWriter.WriteLine($"UserID: {CustomerId}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"FirstName: {FirstName}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"LastName: {LastName}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"Phone: {Phone}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"Mobile: {Mobile}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"Email: {Email}");
//Thread.Sleep(1000);
foreach (var address in Addresses)
{
//Thread.Sleep(1000);
if (address == PrincipalAddress)
stringWriter.WriteLine($"Principal address: {address}");
else
stringWriter.WriteLine($"Secondary address: {address}");
}
try
{
using (var ctx = new EFContext())
{
ctx.Person.Add(this);
ctx.SaveChanges();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}
MainWindow.xaml
<Window x:Class="PostSharp.Samples.Xaml.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xaml="clr-namespace:PostSharp.Samples.Xaml"
xmlns:controls="clr-namespace:PostSharp.Patterns.Model.Controls;assembly=PostSharp.Patterns.Xaml"
Title="Contact Form" Height="352.584" Width="352.753"
x:Name="Window">
<Window.DataContext>
<xaml:CustomerViewModel />
</Window.DataContext>
<DockPanel>
<ToolBarTray DockPanel.Dock="Top">
<ToolBar>
<Button Name="SaveButton" Command="{Binding ElementName=Window, Path=SaveCommand}">Save</Button>
<controls:UndoButton />
<controls:RedoButton />
</ToolBar>
</ToolBarTray>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="29*" />
<ColumnDefinition Width="316*" />
</Grid.ColumnDefinitions>
<Label Content="First Name:" HorizontalAlignment="Left" Margin="10,62,0,0" VerticalAlignment="Top"
Grid.ColumnSpan="2" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,62,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.FirstName, ValidatesOnExceptions=True}" VerticalAlignment="Top"
Width="189" Grid.Column="1" />
<Label Content="Last Name:" HorizontalAlignment="Left" Margin="10,88,0,0" VerticalAlignment="Top"
Grid.ColumnSpan="2" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,92,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.LastName, ValidatesOnExceptions=True}" VerticalAlignment="Top"
Width="189" Grid.Column="1" />
<Label Content="Principal Address:" HorizontalAlignment="Left" Margin="10,119,0,0" VerticalAlignment="Top"
RenderTransformOrigin="-0.105,-0.462" Grid.ColumnSpan="2" />
<ComboBox HorizontalAlignment="Left" Margin="97.846,120,0,0" VerticalAlignment="Top" Width="189"
ItemsSource="{Binding Path=Customer.Addresses}"
SelectedValue="{Binding Path=Customer.PrincipalAddress}" DisplayMemberPath="FullAddress"
Grid.Column="1" />
<xaml:FancyTextBlock HorizontalAlignment="Left" Margin="10,15,0,0" Text="{Binding Path=FullName}"
VerticalAlignment="Top" Width="214" Grid.ColumnSpan="2" />
<Label Content="Line1:" HorizontalAlignment="Left" Margin="11.846,150,0,0" VerticalAlignment="Top"
Grid.Column="1" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,154,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.PrincipalAddress.Line1, ValidatesOnExceptions=True}"
VerticalAlignment="Top" Width="189" Grid.Column="1" />
<Label Content="Town:" HorizontalAlignment="Left" Margin="12.846,176,0,0" VerticalAlignment="Top"
Grid.Column="1" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,182,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.PrincipalAddress.Town, ValidatesOnExceptions=True}"
VerticalAlignment="Top" Width="189" Grid.Column="1" />
<Label Content="User Id:" HorizontalAlignment="Left" Margin="11.846,210,0,0" VerticalAlignment="Top"
Grid.ColumnSpan="2" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,210,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.UserID, ValidatesOnExceptions=True}" VerticalAlignment="Top"
Width="189" Grid.Column="1" />
</Grid>
</DockPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Input;
using Microsoft.Win32;
using PostSharp.Patterns.Collections;
using PostSharp.Patterns.Model;
using PostSharp.Patterns.Recording;
using PostSharp.Patterns.Threading;
using PostSharp.Patterns.Xaml;
namespace PostSharp.Samples.Xaml
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
[NotifyPropertyChanged]
public partial class MainWindow : Window
{
/* private readonly */
public readonly CustomerModel customer = new CustomerModel
{
Email = "2",
Mobile = "3",
Phone = "4",
CustomerId = 1,
FirstName = "Jan",
LastName = "Novak",
Addresses = new AdvisableCollection<AddressModel>
{
new AddressModel
{
Line1 = "Saldova 1G",
Town = "Prague",
Country = "USA"
},
new AddressModel
{
Line1 = "Tyrsova 25",
Town = "Brno",
Country = "USA"
},
new AddressModel
{
Line1 = "Pivorarka 154",
Town = "Pilsen",
Country = "USA"
}
}
};
private readonly Recorder recorder;
public MainWindow()
{
// We need to have a local reference for [NotifyPropertyChanged] to work.
recorder = RecordingServices.DefaultRecorder;
InitializeComponent();
// Register our custom operation formatter.
RecordingServices.OperationFormatter = new MyOperationFormatter(RecordingServices.OperationFormatter);
// Create initial data.
var customerViewModel = new CustomerViewModel {Customer = customer};
customerViewModel.Customer.PrincipalAddress = customerViewModel.Customer.Addresses[0];
// Clear the initialization steps from the recorder.
recorder.Clear();
DataContext = customerViewModel;
}
[Command]
public ICommand SaveCommand { get; private set; }
public bool CanExecuteSave => recorder.UndoOperations.Count > 0;
private void ExecuteSave()
{
var openFileDialog = new SaveFileDialog();
if (openFileDialog.ShowDialog().GetValueOrDefault())
Save(openFileDialog.FileName);
}
[Background]
[DisableUI]
private void Save(string path)
{
customer.Save(path);
}
}
}
packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.2.0" targetFramework="net461" />
<package id="PostSharp" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Aggregation" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Aggregation.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Patterns.Common" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Common.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Patterns.Model" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Model.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Patterns.Threading" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Threading.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Patterns.Xaml" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Xaml.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Redist" version="5.0.40" targetFramework="net461" />
</packages>
PostSharp.Samples.Xaml.csproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\PostSharp.5.0.40\build\PostSharp.props" Condition="Exists('..\..\packages\PostSharp.5.0.40\build\PostSharp.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B10B8456-75F7-4D68-9775-CC87517B07B6}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PostSharp.Samples.Xaml</RootNamespace>
<AssemblyName>PostSharp.Samples.Xaml</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<LangVersion>6</LangVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp, Version=5.0.40.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7">
<HintPath>..\..\packages\PostSharp.Redist.5.0.40\lib\net35-client\PostSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Aggregation">
<HintPath>..\..\packages\PostSharp.Patterns.Aggregation.Redist.5.0.40\lib\net45\PostSharp.Patterns.Aggregation.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Common">
<HintPath>..\..\packages\PostSharp.Patterns.Common.Redist.5.0.40\lib\net46\PostSharp.Patterns.Common.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Model">
<HintPath>..\..\packages\PostSharp.Patterns.Model.Redist.5.0.40\lib\net40\PostSharp.Patterns.Model.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Threading">
<HintPath>..\..\packages\PostSharp.Patterns.Threading.Redist.5.0.40\lib\net45\PostSharp.Patterns.Threading.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Xaml">
<HintPath>..\..\packages\PostSharp.Patterns.Xaml.Redist.5.0.40\lib\net40\PostSharp.Patterns.Xaml.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="FancyTextBlock.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="AddressModel.cs" />
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="CustomerModel.cs" />
<Compile Include="CustomerViewModel.cs" />
<Compile Include="DisableUIAttribute.cs" />
<Compile Include="EFContext.cs" />
<Compile Include="FancyTextBlock.xaml.cs">
<DependentUpon>FancyTextBlock.xaml</DependentUpon>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="ModelBase.cs" />
<Compile Include="MyOperationFormatter.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
<None Include="README.md" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\PostSharp.5.0.40\build\PostSharp.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.5.0.40\build\PostSharp.props'))" />
<Error Condition="!Exists('..\..\packages\PostSharp.5.0.40\build\PostSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.5.0.40\build\PostSharp.targets'))" />
</Target>
<Import Project="..\..\packages\PostSharp.5.0.40\build\PostSharp.targets" Condition="Exists('..\..\packages\PostSharp.5.0.40\build\PostSharp.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
Everything else remain the same, and you should be able to build it and see the exception in CustomerModel.cs line#80 when you change any field in the app and try to save.
You get following ex.Message;
One or more validation errors were detected during model generation:
PostSharp.Samples.Xaml.AddressModel: : EntityType 'AddressModel' has no key defined. Define the key for this EntityType.
<Person>k__BackingField: Name: The specified name is not allowed: '<Person>k__BackingField'.
PostSharp.Samples.Xaml.AddressModel_<Person>k__BackingField: Name: The specified name is not allowed: 'AddressModel_<Person>k__BackingField'.
AddressModel_<Person>k__BackingField_Source: Name: The specified name is not allowed: 'AddressModel_<Person>k__BackingField_Source'.
AddressModel_<Person>k__BackingField_Target: Name: The specified name is not allowed: 'AddressModel_<Person>k__BackingField_Target'.
AddressModels: EntityType: EntitySet 'AddressModels' is based on type 'AddressModel' that has no keys defined.
AddressModel_<Person>k__BackingField: Name: The specified name is not allowed: 'AddressModel_<Person>k__BackingField'.
A new file that was not in the original sample solution, EFContext.cs:
using System.Data.Entity;
namespace PostSharp.Samples.Xaml
{
public class EFContext :DbContext
{
public DbSet<CustomerModel> Person { get; set; }
}
}
You can use OnModelCreating
and modelBuilder.Entity<T>.Ignore(x => x.Property)
in runtime to ignore the failing property programmatically. The following demonstrates changes to EFContext
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
IgnorePostSharpProperties<CustomerModel>(modelBuilder);
IgnorePostSharpProperties<AddressModel>(modelBuilder);
base.OnModelCreating(modelBuilder);
}
public void IgnorePostSharpProperties<T>(DbModelBuilder modelBuilder)
where T : class
{
foreach (PropertyInfo property in typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance))
{
// We don't want properties that are compiler-generated with a special PostSharp name.
if (!property.IsDefined(typeof(CompilerGeneratedAttribute), false) || !property.Name.Contains("<"))
continue;
ParameterExpression paramExpression = Expression.Parameter(typeof(T));
Expression expression = Expression.Lambda(
Expression.Property(paramExpression, property.Name),
paramExpression
);
EntityTypeConfiguration<T> entityTypeConfig = modelBuilder.Entity<T>();
MethodInfo ignoreMethodDefinition = entityTypeConfig.GetType().GetMethod("Ignore", BindingFlags.Public | BindingFlags.Instance);
MethodInfo ignoreMethodInstance = ignoreMethodDefinition.MakeGenericMethod(property.PropertyType);
// Ignore the property.
ignoreMethodInstance.Invoke(entityTypeConfig, new object[] {expression});
}
}