From 2f9003549443ead6e174a53109e4c8419b9c962d Mon Sep 17 00:00:00 2001 From: Chris Kaczor Date: Mon, 14 Jul 2014 17:38:14 -0400 Subject: [PATCH] Update to EF6 --- BrowserCommon.cs | 6 +- Category.cs | 27 + Data/Database.cs | 50 +- Data/Extensions.cs | 22 +- Entities.cs | 22 +- Feed.cs | 59 + FeedAction.cs | 26 + FeedCenter.csproj | 73 +- FeedErrorWindow.xaml.cs | 22 +- FeedItem.cs | 38 + FeedParsers/AtomParser.cs | 15 +- FeedParsers/FeedParserBase.cs | 12 +- FeedParsers/RdfParser.cs | 17 +- FeedParsers/RssParser.cs | 9 +- Feeds/Category.cs | 8 +- Feeds/Feed.cs | 38 +- Feeds/FeedItem.cs | 12 +- MainWindow.xaml.cs | 191 ++-- Model.Context.cs | 34 + Model.Context.tt | 636 +++++++++++ Model.Designer.cs | 1543 +-------------------------- Model.cs | 9 + Model.edmx | 101 +- Model.tt | 726 +++++++++++++ NotificationIcon.cs | 9 +- Options/AboutOptionsPanel.xaml.cs | 2 +- Options/BulkFeedWindow.xaml | 5 +- Options/BulkFeedWindow.xaml.cs | 11 +- Options/DisplayOptionsPanel.xaml.cs | 15 +- Options/FeedWindow.xaml | 8 +- Options/FeedsOptionsPanel.xaml.cs | 87 +- Options/Options.cs | 26 +- Options/UpdateOptionsPanel.xaml.cs | 2 +- Setting.cs | 21 + SettingsStore.cs | 24 +- SplashWindow.xaml.cs | 11 +- VersionCheck.cs | 8 +- app.config | 36 +- packages.config | 5 +- 39 files changed, 2022 insertions(+), 1944 deletions(-) create mode 100644 Category.cs create mode 100644 Feed.cs create mode 100644 FeedAction.cs create mode 100644 FeedItem.cs create mode 100644 Model.Context.cs create mode 100644 Model.Context.tt create mode 100644 Model.cs create mode 100644 Model.tt create mode 100644 Setting.cs diff --git a/BrowserCommon.cs b/BrowserCommon.cs index d7739b8..0a85b66 100644 --- a/BrowserCommon.cs +++ b/BrowserCommon.cs @@ -1,8 +1,8 @@ -using System; -using System.Diagnostics; -using Common.Debug; +using Common.Debug; using Common.Internet; using FeedCenter.Properties; +using System; +using System.Diagnostics; namespace FeedCenter { diff --git a/Category.cs b/Category.cs new file mode 100644 index 0000000..9083a4d --- /dev/null +++ b/Category.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +// +// This code was generated from a template. +// +// Manual changes to this file may cause unexpected behavior in your application. +// Manual changes to this file will be overwritten if the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace FeedCenter +{ + using System; + using System.Collections.Generic; + + public partial class Category + { + public Category() + { + this.Feeds = new HashSet(); + } + + public System.Guid ID { get; set; } + public string Name { get; set; } + + public virtual ICollection Feeds { get; set; } + } +} diff --git a/Data/Database.cs b/Data/Database.cs index 91cec9f..470798a 100644 --- a/Data/Database.cs +++ b/Data/Database.cs @@ -1,13 +1,11 @@ -using System; +using Common.Debug; +using FeedCenter.Properties; +using System; +using System.Collections.Generic; using System.Data.SqlServerCe; using System.IO; -using System.Collections.Generic; using System.Linq; -using Common.Debug; - -using FeedCenter.Properties; - namespace FeedCenter.Data { public static class Database @@ -45,10 +43,10 @@ namespace FeedCenter.Data try { // Open the database file - using (FileStream stream = new FileStream(databasePath, FileMode.Open, FileAccess.Read)) + using (var stream = new FileStream(databasePath, FileMode.Open, FileAccess.Read)) { // Read the file using the binary reader - BinaryReader reader = new BinaryReader(stream); + var reader = new BinaryReader(stream); // Seek to the version signature stream.Seek(16, SeekOrigin.Begin); @@ -81,7 +79,7 @@ namespace FeedCenter.Data Tracer.WriteLine("Creating database engine"); // Create the database engine - using (SqlCeEngine engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) + using (var engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) { Tracer.WriteLine("Creating database"); @@ -95,20 +93,20 @@ namespace FeedCenter.Data } } - private static int getVersion(SqlCeConnection connection) + private static int GetVersion(SqlCeConnection connection) { - string versionString = string.Empty; + string versionString; try { // Check the database version table - using (SqlCeCommand command = new SqlCeCommand("SELECT Value FROM DatabaseVersion", connection)) + using (var command = new SqlCeCommand("SELECT Value FROM DatabaseVersion", connection)) versionString = command.ExecuteScalar().ToString(); } catch (SqlCeException) { // Check the setting table for the version - using (SqlCeCommand command = new SqlCeCommand("SELECT Value FROM Setting WHERE Name = 'DatabaseVersion'", connection)) + using (var command = new SqlCeCommand("SELECT Value FROM Setting WHERE Name = 'DatabaseVersion'", connection)) versionString = command.ExecuteScalar().ToString(); } @@ -125,7 +123,7 @@ namespace FeedCenter.Data Tracer.WriteLine("Getting database file version"); // Get the database file version - SqlServerCeFileVersion fileVersion = GetFileVersion(DatabasePath); + var fileVersion = GetFileVersion(DatabasePath); Tracer.WriteLine("Database file version: {0}", fileVersion); @@ -135,7 +133,7 @@ namespace FeedCenter.Data Tracer.WriteLine("Creating database engine"); // Create the database engine - using (SqlCeEngine engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) + using (var engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) { Tracer.WriteLine("Upgrading database"); @@ -147,13 +145,13 @@ namespace FeedCenter.Data Tracer.WriteLine("Getting database version"); // Create a database connection - using (SqlCeConnection connection = new SqlCeConnection(string.Format("Data Source={0}", DatabasePath))) + using (var connection = new SqlCeConnection(string.Format("Data Source={0}", DatabasePath))) { // Open the connection connection.Open(); // Get the database version - int databaseVersion = getVersion(connection); + var databaseVersion = GetVersion(connection); // Create a dictionary of database upgrade scripts and their version numbers var scriptList = new Dictionary(); @@ -162,10 +160,10 @@ namespace FeedCenter.Data foreach (var property in typeof(Resources).GetProperties().Where(property => property.Name.StartsWith("DatabaseUpdate"))) { // Get the name of the property - string propertyName = property.Name; + var propertyName = property.Name; // Extract the version from the name - int version = int.Parse(propertyName.Substring(propertyName.IndexOf("_", StringComparison.Ordinal) + 1)); + var version = int.Parse(propertyName.Substring(propertyName.IndexOf("_", StringComparison.Ordinal) + 1)); // Add to the script list scriptList[version] = propertyName; @@ -178,7 +176,7 @@ namespace FeedCenter.Data if (databaseVersion <= pair.Key) { // Get the script text - string scriptText = Resources.ResourceManager.GetString(pair.Value); + var scriptText = Resources.ResourceManager.GetString(pair.Value); // Run the script ExecuteScript(scriptText); @@ -192,7 +190,7 @@ namespace FeedCenter.Data Tracer.WriteLine("Creating database engine"); // Create the database engine - using (SqlCeEngine engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) + using (var engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) { Tracer.WriteLine("Shrinking database"); @@ -204,22 +202,22 @@ namespace FeedCenter.Data private static void ExecuteScript(string scriptText) { // Create a database connection - using (SqlCeConnection connection = new SqlCeConnection(string.Format("Data Source={0}", DatabasePath))) + using (var connection = new SqlCeConnection(string.Format("Data Source={0}", DatabasePath))) { // Open the connection connection.Open(); // Setup the delimiters - string[] delimiters = new[] { "\r\nGO\r\n" }; + var delimiters = new[] { "\r\nGO\r\n" }; // Split the script at the delimiters - string[] statements = scriptText.Split(delimiters, StringSplitOptions.RemoveEmptyEntries); + var statements = scriptText.Split(delimiters, StringSplitOptions.RemoveEmptyEntries); // Loop over each statement in the script - foreach (string statement in statements) + foreach (var statement in statements) { // Execute the statement - using (SqlCeCommand command = new SqlCeCommand(statement, connection)) + using (var command = new SqlCeCommand(statement, connection)) command.ExecuteNonQuery(); } } diff --git a/Data/Extensions.cs b/Data/Extensions.cs index 450d561..3c1a021 100644 --- a/Data/Extensions.cs +++ b/Data/Extensions.cs @@ -26,7 +26,7 @@ namespace FeedCenter.Data return null; // Get the first table - DataTable firstTable = dataSet.Tables[0]; + var firstTable = dataSet.Tables[0]; // If the table has no rows then return nothing if (firstTable.Rows.Count == 0) @@ -43,13 +43,13 @@ namespace FeedCenter.Data public static void SetStatement(this SqlCeCommand command, string statement, params object[] parameters) { // Create a new array to hold the updated parameters - object[] formattedParameters = new object[parameters.Length]; + var formattedParameters = new object[parameters.Length]; // Initialize our position - int position = 0; + var position = 0; // Loop over each parameter - foreach (object parameter in parameters) + foreach (var parameter in parameters) { // If the parameter is a DateTime then we need to reformat if (parameter == null) @@ -60,10 +60,10 @@ namespace FeedCenter.Data else if (parameter is DateTime) { // Cast the parameter back to a DateTime - DateTime dateTime = (DateTime) parameter; + var dateTime = (DateTime) parameter; // Convert the DateTime to sortable format - string formatted = dateTime.ToString("s"); + var formatted = dateTime.ToString("s"); // Set into the formatted array formattedParameters[position++] = formatted; @@ -101,7 +101,7 @@ namespace FeedCenter.Data public static void ExecuteNonQuery(this SqlCeConnection connection, string query, params object[] parameters) { // Create the command object - SqlCeCommand command = connection.CreateCommand(); + var command = connection.CreateCommand(); // Set the statement based on the query and parameters command.SetStatement(query, parameters); @@ -115,16 +115,16 @@ namespace FeedCenter.Data public static DataSet ExecuteDataSet(this SqlCeConnection connection, string query, params object[] parameters) { // Create the command object - SqlCeCommand command = connection.CreateCommand(); + var command = connection.CreateCommand(); // Set the statement based on the query and parameters command.SetStatement(query, parameters); // Create a new data adapter - using (SqlCeDataAdapter adapter = new SqlCeDataAdapter(command)) + using (var adapter = new SqlCeDataAdapter(command)) { // Create the new data set - using (DataSet dataSet = new DataSet()) + using (var dataSet = new DataSet()) { //Tracer.WriteLine("Executing SQL query: {0}", command.CommandText); @@ -139,7 +139,7 @@ namespace FeedCenter.Data public static object ExecuteScalar(this SqlCeConnection connection, string query, params object[] parameters) { // Create the command object - SqlCeCommand command = connection.CreateCommand(); + var command = connection.CreateCommand(); // Set the statement based on the query and parameters command.SetStatement(query, parameters); diff --git a/Entities.cs b/Entities.cs index 44960a6..d2f9315 100644 --- a/Entities.cs +++ b/Entities.cs @@ -1,5 +1,6 @@ using System.Collections.ObjectModel; using System.ComponentModel; +using System.Data.Entity.Infrastructure; namespace FeedCenter { @@ -11,7 +12,8 @@ namespace FeedCenter { if (disposing) { - ObjectStateManager.ObjectStateManagerChanged -= HandleObjectStateManagerObjectStateManagerChanged; + var manager = ((IObjectContextAdapter) this).ObjectContext.ObjectStateManager; + manager.ObjectStateManagerChanged -= HandleObjectStateManagerObjectStateManagerChanged; _hookedStateManager = false; } @@ -36,7 +38,8 @@ namespace FeedCenter if (!_hookedStateManager) { - ObjectStateManager.ObjectStateManagerChanged += HandleObjectStateManagerObjectStateManagerChanged; + var manager = ((IObjectContextAdapter) this).ObjectContext.ObjectStateManager; + manager.ObjectStateManagerChanged += HandleObjectStateManagerObjectStateManagerChanged; _hookedStateManager = true; } } @@ -61,7 +64,8 @@ namespace FeedCenter if (!_hookedStateManager) { - ObjectStateManager.ObjectStateManagerChanged += HandleObjectStateManagerObjectStateManagerChanged; + var manager = ((IObjectContextAdapter) this).ObjectContext.ObjectStateManager; + manager.ObjectStateManagerChanged += HandleObjectStateManagerObjectStateManagerChanged; _hookedStateManager = true; } } @@ -80,8 +84,8 @@ namespace FeedCenter { if (_allCategories == null) return; - - Category category = e.Element as Category; + + var category = e.Element as Category; switch (e.Action) { @@ -93,7 +97,7 @@ namespace FeedCenter break; case CollectionChangeAction.Refresh: _allCategories.Clear(); - foreach (Category loopCategory in Categories) + foreach (var loopCategory in Categories) _allCategories.Add(loopCategory); break; } @@ -103,7 +107,7 @@ namespace FeedCenter if (_allFeeds == null) return; - Feed feed = e.Element as Feed; + var feed = e.Element as Feed; switch (e.Action) { @@ -115,10 +119,10 @@ namespace FeedCenter break; case CollectionChangeAction.Refresh: _allFeeds.Clear(); - foreach (Feed loopfeed in Feeds) + foreach (var loopfeed in Feeds) _allFeeds.Add(loopfeed); break; - } + } } } diff --git a/Feed.cs b/Feed.cs new file mode 100644 index 0000000..e7dd4c0 --- /dev/null +++ b/Feed.cs @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +// +// This code was generated from a template. +// +// Manual changes to this file may cause unexpected behavior in your application. +// Manual changes to this file will be overwritten if the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace FeedCenter +{ + using System; + using System.Collections.Generic; + + public partial class Feed + { + public Feed() + { + this.Name = ""; + this.Title = ""; + this.Source = ""; + this.Link = ""; + this.Description = ""; + this.LastChecked = new DateTime(599266080000000000, DateTimeKind.Unspecified); + this.CheckInterval = 60; + this.Enabled = true; + this.Authenticate = false; + this.Username = ""; + this.Password = ""; + this.Domain = ""; + this.LastUpdated = new DateTime(599266080000000000, DateTimeKind.Unspecified); + this.Actions = new HashSet(); + this.Items = new HashSet(); + } + + public System.Guid ID { get; set; } + public string Name { get; set; } + public string Title { get; set; } + public string Source { get; set; } + public string Link { get; set; } + public string Description { get; set; } + public System.DateTime LastChecked { get; set; } + public int CheckInterval { get; set; } + public bool Enabled { get; set; } + public bool Authenticate { get; set; } + public string Username { get; set; } + public string Password { get; set; } + public string Domain { get; set; } + public FeedCenter.FeedReadResult LastReadResult { get; set; } + public System.DateTime LastUpdated { get; set; } + public FeedCenter.FeedItemComparison ItemComparison { get; set; } + public System.Guid CategoryID { get; set; } + public FeedCenter.MultipleOpenAction MultipleOpenAction { get; set; } + + public virtual Category Category { get; set; } + public virtual ICollection Actions { get; set; } + public virtual ICollection Items { get; set; } + } +} diff --git a/FeedAction.cs b/FeedAction.cs new file mode 100644 index 0000000..d853061 --- /dev/null +++ b/FeedAction.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated from a template. +// +// Manual changes to this file may cause unexpected behavior in your application. +// Manual changes to this file will be overwritten if the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace FeedCenter +{ + using System; + using System.Collections.Generic; + + public partial class FeedAction + { + public System.Guid ID { get; set; } + public System.Guid FeedID { get; set; } + public int Field { get; set; } + public string Search { get; set; } + public string Replace { get; set; } + public int Sequence { get; set; } + + public virtual Feed Feed { get; set; } + } +} diff --git a/FeedCenter.csproj b/FeedCenter.csproj index e27b036..9fd1893 100644 --- a/FeedCenter.csproj +++ b/FeedCenter.csproj @@ -132,17 +132,26 @@ ..\Common.Wpf.MarkupExtensions\bin\Release\Common.Wpf.MarkupExtensions.dll + + packages\EntityFramework.6.1.1\lib\net45\EntityFramework.dll + + + packages\EntityFramework.6.1.1\lib\net45\EntityFramework.SqlServer.dll + + + packages\EntityFramework.SqlServerCompact.6.1.1\lib\net45\EntityFramework.SqlServerCompact.dll + + - - - False - bin\Debug\System.Data.SqlServerCe.dll + + True + packages\Microsoft.SqlServer.Compact.4.0.8854.1\lib\net40\System.Data.SqlServerCe.dll - - False - bin\Debug\System.Data.SqlServerCe.Entity.dll + + True + packages\Microsoft.SqlServer.Compact.4.0.8854.1\lib\net40\System.Data.SqlServerCe.Entity.dll @@ -168,12 +177,34 @@ Designer + + Model.tt + + + Model.tt + + + Model.tt + FeedErrorWindow.xaml + + Model.tt + + + True + True + Model.Context.tt + + + True + True + Model.tt + True True @@ -212,6 +243,9 @@ UpdateOptionsPanel.xaml + + Model.tt + SplashWindow.xaml @@ -326,6 +360,16 @@ + + TextTemplatingFileGenerator + Model.Context.cs + Model.edmx + + + TextTemplatingFileGenerator + Model.cs + Model.edmx + @@ -455,12 +499,17 @@ Always + + + - - - - - + + + if not exist "$(TargetDir)x86" md "$(TargetDir)x86" + xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8854.1\NativeBinaries\x86\*.*" "$(TargetDir)x86" + if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64" + xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8854.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64" + - - - - - - - - - - - - - - - - - - - - + - + - - - - + + + + - - - + + + - + @@ -61,8 +42,8 @@ - - + + @@ -72,26 +53,26 @@ - + - + - - - + + + - - + + @@ -102,10 +83,10 @@ - + - + @@ -116,10 +97,10 @@ - + - + @@ -129,6 +110,25 @@ + + + + + + + + + + + + + + + + + + + @@ -170,21 +170,21 @@ - + - - - + + + - + @@ -208,7 +208,7 @@ - + @@ -259,6 +259,9 @@ + + + @@ -350,6 +353,8 @@ + + diff --git a/Model.tt b/Model.tt new file mode 100644 index 0000000..1205534 --- /dev/null +++ b/Model.tt @@ -0,0 +1,726 @@ +<#@ template language="C#" debug="false" hostspecific="true"#> +<#@ include file="EF6.Utility.CS.ttinclude"#><#@ + output extension=".cs"#><# + +const string inputFile = @"Model.edmx"; +var textTransform = DynamicTextTransformation.Create(this); +var code = new CodeGenerationTools(this); +var ef = new MetadataTools(this); +var typeMapper = new TypeMapper(code, ef, textTransform.Errors); +var fileManager = EntityFrameworkTemplateFileManager.Create(this); +var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile); +var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef); + +if (!typeMapper.VerifyCaseInsensitiveTypeUniqueness(typeMapper.GetAllGlobalItems(itemCollection), inputFile)) +{ + return string.Empty; +} + +WriteHeader(codeStringGenerator, fileManager); + +foreach (var entity in typeMapper.GetItemsToGenerate(itemCollection)) +{ + fileManager.StartNewFile(entity.Name + ".cs"); + BeginNamespace(code); +#> +<#=codeStringGenerator.UsingDirectives(inHeader: false)#> +<#=codeStringGenerator.EntityClassOpening(entity)#> +{ +<# + var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity); + var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity); + var complexProperties = typeMapper.GetComplexProperties(entity); + + if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any()) + { +#> + public <#=code.Escape(entity)#>() + { +<# + foreach (var edmProperty in propertiesWithDefaultValues) + { +#> + this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>; +<# + } + + foreach (var navigationProperty in collectionNavigationProperties) + { +#> + this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>(); +<# + } + + foreach (var complexProperty in complexProperties) + { +#> + this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>(); +<# + } +#> + } + +<# + } + + var simpleProperties = typeMapper.GetSimpleProperties(entity); + if (simpleProperties.Any()) + { + foreach (var edmProperty in simpleProperties) + { +#> + <#=codeStringGenerator.Property(edmProperty)#> +<# + } + } + + if (complexProperties.Any()) + { +#> + +<# + foreach(var complexProperty in complexProperties) + { +#> + <#=codeStringGenerator.Property(complexProperty)#> +<# + } + } + + var navigationProperties = typeMapper.GetNavigationProperties(entity); + if (navigationProperties.Any()) + { +#> + +<# + foreach (var navigationProperty in navigationProperties) + { +#> + <#=codeStringGenerator.NavigationProperty(navigationProperty)#> +<# + } + } +#> +} +<# + EndNamespace(code); +} + +foreach (var complex in typeMapper.GetItemsToGenerate(itemCollection)) +{ + fileManager.StartNewFile(complex.Name + ".cs"); + BeginNamespace(code); +#> +<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#> +<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#> +{ +<# + var complexProperties = typeMapper.GetComplexProperties(complex); + var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex); + + if (propertiesWithDefaultValues.Any() || complexProperties.Any()) + { +#> + public <#=code.Escape(complex)#>() + { +<# + foreach (var edmProperty in propertiesWithDefaultValues) + { +#> + this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>; +<# + } + + foreach (var complexProperty in complexProperties) + { +#> + this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>(); +<# + } +#> + } + +<# + } + + var simpleProperties = typeMapper.GetSimpleProperties(complex); + if (simpleProperties.Any()) + { + foreach(var edmProperty in simpleProperties) + { +#> + <#=codeStringGenerator.Property(edmProperty)#> +<# + } + } + + if (complexProperties.Any()) + { +#> + +<# + foreach(var edmProperty in complexProperties) + { +#> + <#=codeStringGenerator.Property(edmProperty)#> +<# + } + } +#> +} +<# + EndNamespace(code); +} + +foreach (var enumType in typeMapper.GetEnumItemsToGenerate(itemCollection)) +{ + fileManager.StartNewFile(enumType.Name + ".cs"); + BeginNamespace(code); +#> +<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#> +<# + if (typeMapper.EnumIsFlags(enumType)) + { +#> +[Flags] +<# + } +#> +<#=codeStringGenerator.EnumOpening(enumType)#> +{ +<# + var foundOne = false; + + foreach (MetadataItem member in typeMapper.GetEnumMembers(enumType)) + { + foundOne = true; +#> + <#=code.Escape(typeMapper.GetEnumMemberName(member))#> = <#=typeMapper.GetEnumMemberValue(member)#>, +<# + } + + if (foundOne) + { + this.GenerationEnvironment.Remove(this.GenerationEnvironment.Length - 3, 1); + } +#> +} +<# + EndNamespace(code); +} + +fileManager.Process(); + +#> +<#+ + +public void WriteHeader(CodeStringGenerator codeStringGenerator, EntityFrameworkTemplateFileManager fileManager) +{ + fileManager.StartHeader(); +#> +//------------------------------------------------------------------------------ +// +// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#> +// +// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#> +// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#> +// +//------------------------------------------------------------------------------ +<#=codeStringGenerator.UsingDirectives(inHeader: true)#> +<#+ + fileManager.EndBlock(); +} + +public void BeginNamespace(CodeGenerationTools code) +{ + var codeNamespace = code.VsNamespaceSuggestion(); + if (!String.IsNullOrEmpty(codeNamespace)) + { +#> +namespace <#=code.EscapeNamespace(codeNamespace)#> +{ +<#+ + PushIndent(" "); + } +} + +public void EndNamespace(CodeGenerationTools code) +{ + if (!String.IsNullOrEmpty(code.VsNamespaceSuggestion())) + { + PopIndent(); +#> +} +<#+ + } +} + +public const string TemplateId = "CSharp_DbContext_Types_EF6"; + +public class CodeStringGenerator +{ + private readonly CodeGenerationTools _code; + private readonly TypeMapper _typeMapper; + private readonly MetadataTools _ef; + + public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef) + { + ArgumentNotNull(code, "code"); + ArgumentNotNull(typeMapper, "typeMapper"); + ArgumentNotNull(ef, "ef"); + + _code = code; + _typeMapper = typeMapper; + _ef = ef; + } + + public string Property(EdmProperty edmProperty) + { + return string.Format( + CultureInfo.InvariantCulture, + "{0} {1} {2} {{ {3}get; {4}set; }}", + Accessibility.ForProperty(edmProperty), + _typeMapper.GetTypeName(edmProperty.TypeUsage), + _code.Escape(edmProperty), + _code.SpaceAfter(Accessibility.ForGetter(edmProperty)), + _code.SpaceAfter(Accessibility.ForSetter(edmProperty))); + } + + public string NavigationProperty(NavigationProperty navProp) + { + var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType()); + return string.Format( + CultureInfo.InvariantCulture, + "{0} {1} {2} {{ {3}get; {4}set; }}", + AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)), + navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType, + _code.Escape(navProp), + _code.SpaceAfter(Accessibility.ForGetter(navProp)), + _code.SpaceAfter(Accessibility.ForSetter(navProp))); + } + + public string AccessibilityAndVirtual(string accessibility) + { + return accessibility + (accessibility != "private" ? " virtual" : ""); + } + + public string EntityClassOpening(EntityType entity) + { + return string.Format( + CultureInfo.InvariantCulture, + "{0} {1}partial class {2}{3}", + Accessibility.ForType(entity), + _code.SpaceAfter(_code.AbstractOption(entity)), + _code.Escape(entity), + _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType))); + } + + public string EnumOpening(SimpleType enumType) + { + return string.Format( + CultureInfo.InvariantCulture, + "{0} enum {1} : {2}", + Accessibility.ForType(enumType), + _code.Escape(enumType), + _code.Escape(_typeMapper.UnderlyingClrType(enumType))); + } + + public void WriteFunctionParameters(EdmFunction edmFunction, Action writeParameter) + { + var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); + foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable)) + { + var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"; + var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")"; + var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))"; + writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit); + } + } + + public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace) + { + var parameters = _typeMapper.GetParameters(edmFunction); + + return string.Format( + CultureInfo.InvariantCulture, + "{0} IQueryable<{1}> {2}({3})", + AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)), + _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), + _code.Escape(edmFunction), + string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray())); + } + + public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace) + { + var parameters = _typeMapper.GetParameters(edmFunction); + + return string.Format( + CultureInfo.InvariantCulture, + "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});", + _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace), + edmFunction.NamespaceName, + edmFunction.Name, + string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()), + _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))); + } + + public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) + { + var parameters = _typeMapper.GetParameters(edmFunction); + var returnType = _typeMapper.GetReturnType(edmFunction); + + var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()); + if (includeMergeOption) + { + paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption"; + } + + return string.Format( + CultureInfo.InvariantCulture, + "{0} {1} {2}({3})", + AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)), + returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">", + _code.Escape(edmFunction), + paramList); + } + + public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) + { + var parameters = _typeMapper.GetParameters(edmFunction); + var returnType = _typeMapper.GetReturnType(edmFunction); + + var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())); + if (includeMergeOption) + { + callParams = ", mergeOption" + callParams; + } + + return string.Format( + CultureInfo.InvariantCulture, + "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});", + returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">", + edmFunction.Name, + callParams); + } + + public string DbSet(EntitySet entitySet) + { + return string.Format( + CultureInfo.InvariantCulture, + "{0} virtual DbSet<{1}> {2} {{ get; set; }}", + Accessibility.ForReadOnlyProperty(entitySet), + _typeMapper.GetTypeName(entitySet.ElementType), + _code.Escape(entitySet)); + } + + public string UsingDirectives(bool inHeader, bool includeCollections = true) + { + return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion()) + ? string.Format( + CultureInfo.InvariantCulture, + "{0}using System;{1}" + + "{2}", + inHeader ? Environment.NewLine : "", + includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "", + inHeader ? "" : Environment.NewLine) + : ""; + } +} + +public class TypeMapper +{ + private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName"; + + private readonly System.Collections.IList _errors; + private readonly CodeGenerationTools _code; + private readonly MetadataTools _ef; + + public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors) + { + ArgumentNotNull(code, "code"); + ArgumentNotNull(ef, "ef"); + ArgumentNotNull(errors, "errors"); + + _code = code; + _ef = ef; + _errors = errors; + } + + public static string FixNamespaces(string typeName) + { + return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial."); + } + + public string GetTypeName(TypeUsage typeUsage) + { + return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null); + } + + public string GetTypeName(EdmType edmType) + { + return GetTypeName(edmType, isNullable: null, modelNamespace: null); + } + + public string GetTypeName(TypeUsage typeUsage, string modelNamespace) + { + return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace); + } + + public string GetTypeName(EdmType edmType, string modelNamespace) + { + return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace); + } + + public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace) + { + if (edmType == null) + { + return null; + } + + var collectionType = edmType as CollectionType; + if (collectionType != null) + { + return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace)); + } + + var typeName = _code.Escape(edmType.MetadataProperties + .Where(p => p.Name == ExternalTypeNameAttributeName) + .Select(p => (string)p.Value) + .FirstOrDefault()) + ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ? + _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) : + _code.Escape(edmType)); + + if (edmType is StructuralType) + { + return typeName; + } + + if (edmType is SimpleType) + { + var clrType = UnderlyingClrType(edmType); + if (!IsEnumType(edmType)) + { + typeName = _code.Escape(clrType); + } + + typeName = FixNamespaces(typeName); + + return clrType.IsValueType && isNullable == true ? + String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) : + typeName; + } + + throw new ArgumentException("edmType"); + } + + public Type UnderlyingClrType(EdmType edmType) + { + ArgumentNotNull(edmType, "edmType"); + + var primitiveType = edmType as PrimitiveType; + if (primitiveType != null) + { + return primitiveType.ClrEquivalentType; + } + + if (IsEnumType(edmType)) + { + return GetEnumUnderlyingType(edmType).ClrEquivalentType; + } + + return typeof(object); + } + + public object GetEnumMemberValue(MetadataItem enumMember) + { + ArgumentNotNull(enumMember, "enumMember"); + + var valueProperty = enumMember.GetType().GetProperty("Value"); + return valueProperty == null ? null : valueProperty.GetValue(enumMember, null); + } + + public string GetEnumMemberName(MetadataItem enumMember) + { + ArgumentNotNull(enumMember, "enumMember"); + + var nameProperty = enumMember.GetType().GetProperty("Name"); + return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null); + } + + public System.Collections.IEnumerable GetEnumMembers(EdmType enumType) + { + ArgumentNotNull(enumType, "enumType"); + + var membersProperty = enumType.GetType().GetProperty("Members"); + return membersProperty != null + ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null) + : Enumerable.Empty(); + } + + public bool EnumIsFlags(EdmType enumType) + { + ArgumentNotNull(enumType, "enumType"); + + var isFlagsProperty = enumType.GetType().GetProperty("IsFlags"); + return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null); + } + + public bool IsEnumType(GlobalItem edmType) + { + ArgumentNotNull(edmType, "edmType"); + + return edmType.GetType().Name == "EnumType"; + } + + public PrimitiveType GetEnumUnderlyingType(EdmType enumType) + { + ArgumentNotNull(enumType, "enumType"); + + return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null); + } + + public string CreateLiteral(object value) + { + if (value == null || value.GetType() != typeof(TimeSpan)) + { + return _code.CreateLiteral(value); + } + + return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks); + } + + public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable types, string sourceFile) + { + ArgumentNotNull(types, "types"); + ArgumentNotNull(sourceFile, "sourceFile"); + + var hash = new HashSet(StringComparer.InvariantCultureIgnoreCase); + if (types.Any(item => !hash.Add(item))) + { + _errors.Add( + new CompilerError(sourceFile, -1, -1, "6023", + String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict")))); + return false; + } + return true; + } + + public IEnumerable GetEnumItemsToGenerate(IEnumerable itemCollection) + { + return GetItemsToGenerate(itemCollection) + .Where(e => IsEnumType(e)); + } + + public IEnumerable GetItemsToGenerate(IEnumerable itemCollection) where T: EdmType + { + return itemCollection + .OfType() + .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName)) + .OrderBy(i => i.Name); + } + + public IEnumerable GetAllGlobalItems(IEnumerable itemCollection) + { + return itemCollection + .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i)) + .Select(g => GetGlobalItemName(g)); + } + + public string GetGlobalItemName(GlobalItem item) + { + if (item is EdmType) + { + return ((EdmType)item).Name; + } + else + { + return ((EntityContainer)item).Name; + } + } + + public IEnumerable GetSimpleProperties(EntityType type) + { + return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type); + } + + public IEnumerable GetSimpleProperties(ComplexType type) + { + return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type); + } + + public IEnumerable GetComplexProperties(EntityType type) + { + return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type); + } + + public IEnumerable GetComplexProperties(ComplexType type) + { + return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type); + } + + public IEnumerable GetPropertiesWithDefaultValues(EntityType type) + { + return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null); + } + + public IEnumerable GetPropertiesWithDefaultValues(ComplexType type) + { + return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null); + } + + public IEnumerable GetNavigationProperties(EntityType type) + { + return type.NavigationProperties.Where(np => np.DeclaringType == type); + } + + public IEnumerable GetCollectionNavigationProperties(EntityType type) + { + return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many); + } + + public FunctionParameter GetReturnParameter(EdmFunction edmFunction) + { + ArgumentNotNull(edmFunction, "edmFunction"); + + var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters"); + return returnParamsProperty == null + ? edmFunction.ReturnParameter + : ((IEnumerable)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault(); + } + + public bool IsComposable(EdmFunction edmFunction) + { + ArgumentNotNull(edmFunction, "edmFunction"); + + var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute"); + return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null); + } + + public IEnumerable GetParameters(EdmFunction edmFunction) + { + return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef); + } + + public TypeUsage GetReturnType(EdmFunction edmFunction) + { + var returnParam = GetReturnParameter(edmFunction); + return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage); + } + + public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption) + { + var returnType = GetReturnType(edmFunction); + return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType; + } +} + +public static void ArgumentNotNull(T arg, string name) where T : class +{ + if (arg == null) + { + throw new ArgumentNullException(name); + } +} +#> \ No newline at end of file diff --git a/NotificationIcon.cs b/NotificationIcon.cs index 0b70c66..1e26970 100644 --- a/NotificationIcon.cs +++ b/NotificationIcon.cs @@ -1,6 +1,5 @@ -using System.Windows.Forms; - -using FeedCenter.Properties; +using FeedCenter.Properties; +using System.Windows.Forms; namespace FeedCenter { @@ -19,9 +18,9 @@ namespace FeedCenter _notificationIcon.DoubleClick += HandleNotificationIconDoubleClick; // Setup the menu - ContextMenuStrip contextMenuStrip = new ContextMenuStrip(); + var contextMenuStrip = new ContextMenuStrip(); - ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(Resources.NotificationIconContextMenuLocked, null, HandleLockWindowClicked) + var toolStripMenuItem = new ToolStripMenuItem(Resources.NotificationIconContextMenuLocked, null, HandleLockWindowClicked) { Checked = Settings.Default.WindowLocked }; diff --git a/Options/AboutOptionsPanel.xaml.cs b/Options/AboutOptionsPanel.xaml.cs index 6716d69..0e99ef1 100644 --- a/Options/AboutOptionsPanel.xaml.cs +++ b/Options/AboutOptionsPanel.xaml.cs @@ -3,7 +3,7 @@ using System.Reflection; namespace FeedCenter.Options { - public partial class AboutOptionsPanel + public partial class AboutOptionsPanel { public AboutOptionsPanel() { diff --git a/Options/BulkFeedWindow.xaml b/Options/BulkFeedWindow.xaml index af6cd70..7817c57 100644 --- a/Options/BulkFeedWindow.xaml +++ b/Options/BulkFeedWindow.xaml @@ -7,6 +7,7 @@ xmlns:my="clr-namespace:FeedCenter.Properties" xmlns:Options="clr-namespace:FeedCenter.Options" xmlns:LinkControl="clr-namespace:Common.Wpf.LinkControl;assembly=Common.Wpf" + xmlns:feedCenter="clr-namespace:FeedCenter" WindowStartupLocation="CenterOwner" Icon="/FeedCenter;component/Resources/Application.ico" FocusManager.FocusedElement="{Binding ElementName=feedLinkFilterText}"> @@ -97,9 +98,9 @@ ToolTip="{x:Static my:Resources.DisableHint}" IsEnabled="False"> + Tag="{x:Static feedCenter:MultipleOpenAction.IndividualPages}" /> + Tag="{x:Static feedCenter:MultipleOpenAction.SinglePage}" />