From f1fc7275f0af7ddd5dbe6e8854cac422e9f5cc5c Mon Sep 17 00:00:00 2001 From: mgroves Date: Sun, 2 Jan 2011 21:33:01 -0500 Subject: [PATCH 1/6] now pulling config from DB instead of hardcoded list --- MonoStockPortfolio.Core/AndroidSqliteBase.cs | 46 +++++++++++ .../Config/AndroidSqliteConfigRepository.cs | 27 +++++- .../MonoStockPortfolio.Core.csproj | 1 + .../AndroidSqlitePortfolioRepository.cs | 82 ++++--------------- MonoStockPortfolio.Entities/StockDataItem.cs | 18 ++-- 5 files changed, 100 insertions(+), 74 deletions(-) create mode 100644 MonoStockPortfolio.Core/AndroidSqliteBase.cs diff --git a/MonoStockPortfolio.Core/AndroidSqliteBase.cs b/MonoStockPortfolio.Core/AndroidSqliteBase.cs new file mode 100644 index 0000000..b75834e --- /dev/null +++ b/MonoStockPortfolio.Core/AndroidSqliteBase.cs @@ -0,0 +1,46 @@ +using Android.Content; +using Android.Database.Sqlite; +using Android.Util; + +namespace MonoStockPortfolio.Core +{ + public abstract class AndroidSqliteBase : SQLiteOpenHelper + { + public const string PORTFOLIO_TABLE_NAME = "Portfolios"; + public const string POSITION_TABLE_NAME = "Positions"; + public const string CONFIG_TABLE_NAME = "Config"; + + public const string DATABASE_NAME = "stockportfolio.db"; + public const int DATABASE_VERSION = 1; + + protected AndroidSqliteBase(Context context) + : base(context, DATABASE_NAME, null, DATABASE_VERSION) + { + } + + protected SQLiteDatabase Db { get { return WritableDatabase; } } + + public override void OnCreate(SQLiteDatabase db) + { + db.ExecSQL("CREATE TABLE " + PORTFOLIO_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT)"); + db.ExecSQL("CREATE TABLE " + POSITION_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, Ticker TEXT, Shares REAL, PricePerShare REAL, ContainingPortfolioID INT)"); + db.ExecSQL("CREATE TABLE " + CONFIG_TABLE_NAME + " (StockItems TEXT)"); + + db.ExecSQL("INSERT INTO " + CONFIG_TABLE_NAME + " (StockItems) VALUES ('2,0,1,3')"); + db.ExecSQL("INSERT INTO " + PORTFOLIO_TABLE_NAME + " (Name) VALUES ('Sample portfolio')"); + db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('GOOG', '500', '593.97', 1)"); + db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('AMZN', '500', '180.00', 1)"); + db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('AAPL', '500', '322.56', 1)"); + db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('MSFT', '500', '27.91', 1)"); + db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('NOVL', '500', '5.92', 1)"); + db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('S', '500', '4.23', 1)"); + db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('VZ', '500', '35.78', 1)"); + db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('T', '500', '29.38', 1)"); + } + + public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) + { + Log.W("Upgrade", "Nothing to upgrade"); + } + } +} \ No newline at end of file diff --git a/MonoStockPortfolio.Core/Config/AndroidSqliteConfigRepository.cs b/MonoStockPortfolio.Core/Config/AndroidSqliteConfigRepository.cs index aa80e5c..2f94799 100644 --- a/MonoStockPortfolio.Core/Config/AndroidSqliteConfigRepository.cs +++ b/MonoStockPortfolio.Core/Config/AndroidSqliteConfigRepository.cs @@ -1,11 +1,36 @@ using System.Collections.Generic; +using System.Linq; +using Android.Content; using MonoStockPortfolio.Entities; namespace MonoStockPortfolio.Core.Config { - public class AndroidSqliteConfigRepository : IConfigRepository + public class AndroidSqliteConfigRepository : AndroidSqliteBase, IConfigRepository { + public AndroidSqliteConfigRepository(Context context) : base(context) + { } + public IEnumerable GetStockItems() + { + var cursor = Db.Query(CONFIG_TABLE_NAME, new[] { "StockItems" }, null, null, null, null, null); + string stockItemsCsv = null; + if (cursor.Count > 0) + { + cursor.MoveToNext(); + stockItemsCsv = cursor.GetString(0); + if (!cursor.IsClosed) cursor.Close(); + } + + if (string.IsNullOrEmpty(stockItemsCsv)) + { + return DefaultItems(); + } + + return stockItemsCsv.Split(',').Select(i => (StockDataItem)int.Parse(i)); + } + + // this should never be called, but it's here anyway in case of some catastrophe + private static IEnumerable DefaultItems() { var items = new List(); items.Add(StockDataItem.Ticker); diff --git a/MonoStockPortfolio.Core/MonoStockPortfolio.Core.csproj b/MonoStockPortfolio.Core/MonoStockPortfolio.Core.csproj index eaad376..fcad5df 100644 --- a/MonoStockPortfolio.Core/MonoStockPortfolio.Core.csproj +++ b/MonoStockPortfolio.Core/MonoStockPortfolio.Core.csproj @@ -46,6 +46,7 @@ + diff --git a/MonoStockPortfolio.Core/PortfolioRepositories/AndroidSqlitePortfolioRepository.cs b/MonoStockPortfolio.Core/PortfolioRepositories/AndroidSqlitePortfolioRepository.cs index 8881496..efeb042 100644 --- a/MonoStockPortfolio.Core/PortfolioRepositories/AndroidSqlitePortfolioRepository.cs +++ b/MonoStockPortfolio.Core/PortfolioRepositories/AndroidSqlitePortfolioRepository.cs @@ -7,25 +7,15 @@ using MonoStockPortfolio.Entities; namespace MonoStockPortfolio.Core.PortfolioRepositories { - public class AndroidSqlitePortfolioRepository : IPortfolioRepository + public class AndroidSqlitePortfolioRepository : AndroidSqliteBase, IPortfolioRepository { - private OpenHelper _dbHelper; - private SQLiteDatabase _db; - private const string PORTFOLIO_TABLE_NAME = "Portfolios"; - private const string DATABASE_NAME = "stockportfolio.db"; - private const int DATABASE_VERSION = 1; - private const string POSITION_TABLE_NAME = "Positions"; - - public AndroidSqlitePortfolioRepository(Context context) - { - _dbHelper = new OpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION); - _db = _dbHelper.WritableDatabase; - } + public AndroidSqlitePortfolioRepository(Context context) : base(context) + { } public IList GetAllPortfolios() { var list = new List(); - var cursor = _db.Query(PORTFOLIO_TABLE_NAME, new[] {"id", "Name"}, null, null, null, null, null); + var cursor = Db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, null, null, null, null, null); if(cursor.Count > 0) { while(cursor.MoveToNext()) @@ -41,7 +31,7 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories public Portfolio GetPortfolioById(long portfolioId) { - var cursor = _db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, " ID = " + portfolioId, null, null, null, null); + var cursor = Db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, " ID = " + portfolioId, null, null, null, null); if (cursor.Count > 0) { cursor.MoveToNext(); @@ -67,12 +57,12 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories public void DeletePortfolioById(int portfolioId) { - _db.BeginTransaction(); + Db.BeginTransaction(); try { - _db.Delete(PORTFOLIO_TABLE_NAME, "id = " + portfolioId, null); - _db.Delete(POSITION_TABLE_NAME, "ContainingPortfolioID = " + portfolioId, null); - _db.SetTransactionSuccessful(); + Db.Delete(PORTFOLIO_TABLE_NAME, "id = " + portfolioId, null); + Db.Delete(POSITION_TABLE_NAME, "ContainingPortfolioID = " + portfolioId, null); + Db.SetTransactionSuccessful(); } catch (SQLiteException) { @@ -80,13 +70,13 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories } finally { - _db.EndTransaction(); + Db.EndTransaction(); } } public Portfolio GetPortfolioByName(string portfolioName) { - var cursor = _db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, " Name = '" + portfolioName + "'", null, null, null, null); + var cursor = Db.Query(PORTFOLIO_TABLE_NAME, new[] { "id", "Name" }, " Name = '" + portfolioName + "'", null, null, null, null); if (cursor.Count > 0) { cursor.MoveToNext(); @@ -100,14 +90,14 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories public void DeletePositionById(long positionId) { - _db.Delete(POSITION_TABLE_NAME, "id = " + positionId, null); + Db.Delete(POSITION_TABLE_NAME, "id = " + positionId, null); } public Position GetPositionById(long positionId) { Position position = null; - var cursor = _db.Query(POSITION_TABLE_NAME, new[] { "id", "Ticker", "Shares", "PricePerShare" }, " id = " + positionId, null, null, null, null); + var cursor = Db.Query(POSITION_TABLE_NAME, new[] { "id", "Ticker", "Shares", "PricePerShare" }, " id = " + positionId, null, null, null, null); if (cursor.Count > 0) { while (cursor.MoveToNext()) @@ -126,7 +116,7 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories { var list = new List(); - var cursor = _db.Query(POSITION_TABLE_NAME, new[] { "id", "Ticker", "Shares", "PricePerShare" }, " ContainingPortfolioID = " + portfolioId, null, null, null, null); + var cursor = Db.Query(POSITION_TABLE_NAME, new[] { "id", "Ticker", "Shares", "PricePerShare" }, " ContainingPortfolioID = " + portfolioId, null, null, null, null); if (cursor.Count > 0) { while (cursor.MoveToNext()) @@ -157,23 +147,23 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories private void UpdateExistingPortfolio(Portfolio portfolio) { var portfolioID = portfolio.ID ?? -1; - Log.E("UpdateExistingPortfolio", "Portfolios updated: " + _db.Update(PORTFOLIO_TABLE_NAME, GetPortfolioContentValues(portfolio), "id = " + portfolioID, null)); + Log.E("UpdateExistingPortfolio", "Portfolios updated: " + Db.Update(PORTFOLIO_TABLE_NAME, GetPortfolioContentValues(portfolio), "id = " + portfolioID, null)); } private void InsertNewPortfolio(Portfolio portfolio) { - Log.E("InsertNewPortfolio", "Portfolios inserted: " + _db.Insert(PORTFOLIO_TABLE_NAME, null, GetPortfolioContentValues(portfolio))); + Log.E("InsertNewPortfolio", "Portfolios inserted: " + Db.Insert(PORTFOLIO_TABLE_NAME, null, GetPortfolioContentValues(portfolio))); } private void UpdateExistingPosition(Position position) { var positionID = position.ID ?? -1; - Log.E("UpdateExistingPosition", "Positions updated: " + _db.Update(POSITION_TABLE_NAME, GetPositionContentValues(position), "id = " + positionID, null)); + Log.E("UpdateExistingPosition", "Positions updated: " + Db.Update(POSITION_TABLE_NAME, GetPositionContentValues(position), "id = " + positionID, null)); } private void InsertNewPosition(Position position) { - Log.E("InsertNewPosition", "Positions inserted: " + _db.Insert(POSITION_TABLE_NAME, null, GetPositionContentValues(position))); + Log.E("InsertNewPosition", "Positions inserted: " + Db.Insert(POSITION_TABLE_NAME, null, GetPositionContentValues(position))); } private static ContentValues GetPortfolioContentValues(Portfolio portfolio) @@ -192,41 +182,5 @@ namespace MonoStockPortfolio.Core.PortfolioRepositories positionValues.Put("ContainingPortfolioID", position.ContainingPortfolioID); return positionValues; } - - - - - - - - - private class OpenHelper : SQLiteOpenHelper - { - public OpenHelper(Context context, string name, SQLiteDatabase.ICursorFactory factory, int version) - : base(context, name, factory, version) - { - } - - public override void OnCreate(SQLiteDatabase db) - { - db.ExecSQL("CREATE TABLE " + PORTFOLIO_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT)"); - db.ExecSQL("CREATE TABLE " + POSITION_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, Ticker TEXT, Shares REAL, PricePerShare REAL, ContainingPortfolioID INT)"); - - db.ExecSQL("INSERT INTO " + PORTFOLIO_TABLE_NAME + " (Name) VALUES ('Sample portfolio')"); - db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('GOOG', '500', '593.97', 1)"); - db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('AMZN', '500', '180.00', 1)"); - db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('AAPL', '500', '322.56', 1)"); - db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('MSFT', '500', '27.91', 1)"); - db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('NOVL', '500', '5.92', 1)"); - db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('S', '500', '4.23', 1)"); - db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('VZ', '500', '35.78', 1)"); - db.ExecSQL("INSERT INTO " + POSITION_TABLE_NAME + " (Ticker, Shares, PricePerShare, ContainingPortfolioID) VALUES ('T', '500', '29.38', 1)"); - } - - public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) - { - Log.W("Upgrade", "Nothing to upgrade"); - } - } } } \ No newline at end of file diff --git a/MonoStockPortfolio.Entities/StockDataItem.cs b/MonoStockPortfolio.Entities/StockDataItem.cs index 929dd94..f1020d5 100644 --- a/MonoStockPortfolio.Entities/StockDataItem.cs +++ b/MonoStockPortfolio.Entities/StockDataItem.cs @@ -3,22 +3,22 @@ namespace MonoStockPortfolio.Entities public enum StockDataItem { [StringValue("Change")] - Change, + Change = 0, [StringValue("Gain/Loss")] - GainLoss, + GainLoss = 1, [StringValue("Ticker")] - Ticker, + Ticker = 2, [StringValue("Time")] - Time, + Time = 3, [StringValue("Volume")] - Volume, + Volume = 4, [StringValue("Price")] - LastTradePrice, + LastTradePrice = 5, [StringValue("Price-RT")] - RealTimeLastTradeWithTime, + RealTimeLastTradeWithTime = 6, [StringValue("Change-RT")] - ChangeRealTime, + ChangeRealTime = 7, [StringValue("Gain/Loss-RT")] - GainLossRealTime + GainLossRealTime = 8 } } \ No newline at end of file From 78f76cbc492edba3197c263ff31dab4d2f824dd4 Mon Sep 17 00:00:00 2001 From: mgroves Date: Sun, 2 Jan 2011 23:11:15 -0500 Subject: [PATCH 2/6] working on config screen, items don't check or save properly --- .../Config/AndroidSqliteConfigRepository.cs | 8 +++ .../Config/IConfigRepository.cs | 1 + MonoStockPortfolio.Core/EnumExtensions.cs | 14 ++++ .../Activites/ConfigActivity.cs | 69 +++++++++++++++++++ MonoStockPortfolio/Activites/MainActivity.cs | 27 ++++++++ MonoStockPortfolio/MonoStockPortfolio.csproj | 4 ++ .../Resources/Resource.Designer.cs | 7 +- .../Resources/layout/config.xml | 9 +++ MonoStockPortfolio/Resources/layout/main.xml | 15 ++-- 9 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 MonoStockPortfolio/Activites/ConfigActivity.cs create mode 100644 MonoStockPortfolio/Resources/layout/config.xml diff --git a/MonoStockPortfolio.Core/Config/AndroidSqliteConfigRepository.cs b/MonoStockPortfolio.Core/Config/AndroidSqliteConfigRepository.cs index 2f94799..588347e 100644 --- a/MonoStockPortfolio.Core/Config/AndroidSqliteConfigRepository.cs +++ b/MonoStockPortfolio.Core/Config/AndroidSqliteConfigRepository.cs @@ -29,6 +29,14 @@ namespace MonoStockPortfolio.Core.Config return stockItemsCsv.Split(',').Select(i => (StockDataItem)int.Parse(i)); } + public void UpdateStockItems(List stockDataItems) + { + var stockItemsCsv = string.Join(",", stockDataItems.Select(i => ((int) i).ToString()).ToArray()); + var contentValues = new ContentValues(); + contentValues.Put("StockItems", stockItemsCsv); + Db.Update(CONFIG_TABLE_NAME, contentValues, null, null); + } + // this should never be called, but it's here anyway in case of some catastrophe private static IEnumerable DefaultItems() { diff --git a/MonoStockPortfolio.Core/Config/IConfigRepository.cs b/MonoStockPortfolio.Core/Config/IConfigRepository.cs index d8e2cbf..2cd9755 100644 --- a/MonoStockPortfolio.Core/Config/IConfigRepository.cs +++ b/MonoStockPortfolio.Core/Config/IConfigRepository.cs @@ -6,5 +6,6 @@ namespace MonoStockPortfolio.Core.Config public interface IConfigRepository { IEnumerable GetStockItems(); + void UpdateStockItems(List stockDataItems); } } \ No newline at end of file diff --git a/MonoStockPortfolio.Core/EnumExtensions.cs b/MonoStockPortfolio.Core/EnumExtensions.cs index dd1e98d..fa8a8a5 100644 --- a/MonoStockPortfolio.Core/EnumExtensions.cs +++ b/MonoStockPortfolio.Core/EnumExtensions.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using MonoStockPortfolio.Entities; namespace MonoStockPortfolio.Core @@ -21,5 +24,16 @@ namespace MonoStockPortfolio.Core } return string.Empty; } + + public static IEnumerable GetValues(this Enum value) + { + var enumerations = new List(); + var fields = value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public); + foreach (var fieldInfo in fields) + { + enumerations.Add((Enum)fieldInfo.GetValue(value)); + } + return enumerations.Cast(); + } } } \ No newline at end of file diff --git a/MonoStockPortfolio/Activites/ConfigActivity.cs b/MonoStockPortfolio/Activites/ConfigActivity.cs new file mode 100644 index 0000000..f024124 --- /dev/null +++ b/MonoStockPortfolio/Activites/ConfigActivity.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.Linq; +using Android.App; +using Android.Content; +using Android.OS; +using Android.Preferences; +using MonoStockPortfolio.Core.Config; +using MonoStockPortfolio.Entities; +using MonoStockPortfolio.Framework; +using MonoStockPortfolio.Core; + +namespace MonoStockPortfolio.Activites +{ + [Activity(Label = "Config")] + public class ConfigActivity : PreferenceActivity + { + [IoC] private IConfigRepository _repo; + + private bool[] _allitemschecked; + private StockDataItem[] _allStockItems; + + protected override void OnCreate(Bundle bundle) + { + base.OnCreate(bundle); + + AddPreferencesFromResource(Resource.layout.config); + + _allStockItems = StockDataItem.Change.GetValues().ToArray(); + var checkedItems = _repo.GetStockItems(); + _allitemschecked = _allStockItems.Select(i => checkedItems.Contains(i)).ToArray(); + + var customPref = FindPreference("customStockItems"); + customPref.PreferenceClick += customPref_PreferenceClick; + } + + bool customPref_PreferenceClick(Preference preference) + { + var stockItemsDisplay = _allStockItems.Select(i => i.GetStringValue()).Cast>().ToArray(); + + var dialog = new AlertDialog.Builder(this) + .SetTitle("Select columns") + .SetMultiChoiceItems(stockItemsDisplay, _allitemschecked, clickCallback) + .SetPositiveButton("Save", okCallback) + .Create(); + dialog.Show(); + return true; + } + + private void okCallback(object sender, DialogClickEventArgs e) + { + var list = new List(); + for (int i = 0; i < _allitemschecked.Length; i++) + { + if (_allitemschecked[i]) + { + list.Add(_allStockItems[i]); + } + } + _repo.UpdateStockItems(list); + } + + private void clickCallback(object sender, DialogMultiChoiceClickEventArgs e) + { + _allitemschecked[e.Which] = e.IsChecked; + } + + public static string ClassName { get { return "monostockportfolio.activites.ConfigActivity"; } } + } +} \ No newline at end of file diff --git a/MonoStockPortfolio/Activites/MainActivity.cs b/MonoStockPortfolio/Activites/MainActivity.cs index 5f05a49..722d5a2 100644 --- a/MonoStockPortfolio/Activites/MainActivity.cs +++ b/MonoStockPortfolio/Activites/MainActivity.cs @@ -4,6 +4,7 @@ using System.Linq; using Android.App; using Android.Content; using Android.OS; +using Android.Views; using Android.Widget; using MonoStockPortfolio.Core.PortfolioRepositories; using MonoStockPortfolio.Entities; @@ -79,6 +80,32 @@ namespace MonoStockPortfolio.Activites return base.OnContextItemSelected(item); } + public override bool OnCreateOptionsMenu(IMenu menu) + { + var configItem = menu.Add(0, 1, 1, "Config"); + configItem.SetIcon(Android.R.Drawable.IcMenuPreferences); + var exitItem = menu.Add(0, 1, 1, "Exit"); + exitItem.SetIcon(Android.R.Drawable.IcMenuCloseClearCancel); + return true; + } + + public override bool OnOptionsItemSelected(IMenuItem item) + { + switch (item.Title.ToS()) + { + case "Config": + var intent = new Intent(); + intent.SetClassName(this, ConfigActivity.ClassName); + StartActivityForResult(intent, 0); + return true; + case "Exit": + Finish(); + return true; + default: + return base.OnOptionsItemSelected(item); + } + } + private void listView_ItemClick(object sender, ItemEventArgs e) { var intent = new Intent(); diff --git a/MonoStockPortfolio/MonoStockPortfolio.csproj b/MonoStockPortfolio/MonoStockPortfolio.csproj index b8229dd..ca2addb 100644 --- a/MonoStockPortfolio/MonoStockPortfolio.csproj +++ b/MonoStockPortfolio/MonoStockPortfolio.csproj @@ -48,6 +48,7 @@ + EditPositionActivity.cs @@ -127,6 +128,9 @@ + + + + \ No newline at end of file diff --git a/MonoStockPortfolio.Tests/PostSharp.Custom.targets b/MonoStockPortfolio.Tests/PostSharp.Custom.targets new file mode 100644 index 0000000..38368c7 --- /dev/null +++ b/MonoStockPortfolio.Tests/PostSharp.Custom.targets @@ -0,0 +1,6 @@ + + + + Silverlight20 + + \ No newline at end of file diff --git a/MonoStockPortfolio.Tests/Properties/AssemblyInfo.cs b/MonoStockPortfolio.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2c0dd27 --- /dev/null +++ b/MonoStockPortfolio.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MonoStockPortfolio.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("MonoStockPortfolio.Tests")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MonoStockPortfolio.sln b/MonoStockPortfolio.sln index 734f6db..10045dc 100644 --- a/MonoStockPortfolio.sln +++ b/MonoStockPortfolio.sln @@ -12,6 +12,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoStockPortfolio.Core", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoStockPortfolio.Entities", "MonoStockPortfolio.Entities\MonoStockPortfolio.Entities.csproj", "{05A57650-3B41-46FF-9EAD-9112B5EFBEED}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoStockPortfolio.Tests", "MonoStockPortfolio.Tests\MonoStockPortfolio.Tests.csproj", "{C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -30,6 +32,10 @@ Global {05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Debug|Any CPU.Build.0 = Debug|Any CPU {05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Release|Any CPU.ActiveCfg = Release|Any CPU {05A57650-3B41-46FF-9EAD-9112B5EFBEED}.Release|Any CPU.Build.0 = Release|Any CPU + {C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C2797FAB-AFAB-49F6-9131-FC9BF03CAB9D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MonoStockPortfolio/Framework/IttyBittyIoC.cs b/MonoStockPortfolio/Framework/IttyBittyIoC.cs new file mode 100644 index 0000000..6b2fb6a --- /dev/null +++ b/MonoStockPortfolio/Framework/IttyBittyIoC.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace MonoStockPortfolio.Framework +{ + public static class IttyBittyIoC + { + [AttributeUsage(AttributeTargets.Constructor)] + public class InjectionConstructorAttribute : Attribute + { } + + private enum DependencyType + { + None = 0, // Type is unset + Delegate, // A builder function + Instance, // A specific instance + Singleton, // Dynamically created singleton + Transient // Dynamically created transient object + } + + private class DependencyInfo + { + public object Dependency { get; private set; } + public DependencyType DependencyType { get; private set; } + + public DependencyInfo(DependencyType dependencyType, object dependency) + { + DependencyType = dependencyType; + Dependency = dependency; + } + } + + private readonly static IDictionary dependencies = new Dictionary(); + private readonly static IDictionary instances = new Dictionary(); + + public static void Register(TContract instance) + { + dependencies[typeof(TContract)] = new DependencyInfo(DependencyType.Instance, instance); + instances[typeof(TContract)] = instance; + } + + public static void Register() + { + Register(false); + } + + public static void Register(bool isSingleton) + { + DependencyType dependencyType = isSingleton ? DependencyType.Singleton : DependencyType.Transient; + dependencies[typeof(TContract)] = new DependencyInfo(dependencyType, typeof(TImplementation)); + } + + public static void Register(Func builder) + { + dependencies[typeof(TContract)] = new DependencyInfo(DependencyType.Delegate, builder); + } + + public static TContract Resolve() + { + return (TContract)Resolve(typeof(TContract)); + } + + public static object Resolve(Type contract) + { + if (!dependencies.ContainsKey(contract)) + throw new InvalidOperationException(string.Format("Unable to resolve type '{0}'.", contract)); + if (instances.ContainsKey(contract)) + return instances[contract]; + var dependency = dependencies[contract]; + if (dependency.DependencyType == DependencyType.Delegate) + return ((Delegate)dependency.Dependency).DynamicInvoke(); + + var constructorInfo = ((Type)dependency.Dependency).GetConstructors() + .OrderByDescending(o => (o.GetCustomAttributes(typeof(InjectionConstructorAttribute), false).Count())) + .ThenByDescending(o => (o.GetParameters().Length)) + .First(); + var parameterInfos = constructorInfo.GetParameters(); + + object instance; + if (parameterInfos.Length == 0) + { + instance = Activator.CreateInstance((Type)dependency.Dependency); + } + else + { + var parameters = new List(parameterInfos.Length); + foreach (ParameterInfo parameterInfo in parameterInfos) + { + parameters.Add(Resolve(parameterInfo.ParameterType)); + } + instance = constructorInfo.Invoke(parameters.ToArray()); + } + + if (dependency.DependencyType == DependencyType.Singleton) + { + instances[contract] = instance; + } + + return instance; + } + } +} \ No newline at end of file diff --git a/MonoStockPortfolio/Framework/ServiceLocator.cs b/MonoStockPortfolio/Framework/ServiceLocator.cs index ab9ee1e..7c0b45a 100644 --- a/MonoStockPortfolio/Framework/ServiceLocator.cs +++ b/MonoStockPortfolio/Framework/ServiceLocator.cs @@ -1,88 +1,28 @@ using System; -using System.Collections.Generic; using Android.Content; using MonoStockPortfolio.Core.Config; using MonoStockPortfolio.Core.PortfolioRepositories; using MonoStockPortfolio.Core.Services; using MonoStockPortfolio.Core.StockData; -using MonoStockPortfolio.Entities; -using TinyIoC; namespace MonoStockPortfolio.Framework { public static class ServiceLocator { public static Context Context { get; set; } - private static TinyIoCContainer _container; + + static ServiceLocator() + { + //IttyBittyIoC.Register(Context); + IttyBittyIoC.Register(() => new GoogleStockDataProvider()); + IttyBittyIoC.Register(() => new PortfolioService(new AndroidSqlitePortfolioRepository(Context), new GoogleStockDataProvider())); + IttyBittyIoC.Register(() => new AndroidSqlitePortfolioRepository(Context)); + IttyBittyIoC.Register(() => new AndroidSqliteConfigRepository(Context)); + } public static object Get(Type serviceType) { - if (_container == null) - { - _container = RegisterTypes(); - } - return _container.Resolve(serviceType); - } - - private static TinyIoCContainer RegisterTypes() - { - var container = TinyIoCContainer.Current; - - container.Register(Context); - container.Register().AsMultiInstance(); // works - container.Register().AsMultiInstance(); // works - container.Register().AsMultiInstance(); // error - //container.Register().AsMultiInstance(); // error - - return container; - } - } - - public class Whatever : IPortfolioRepository - { - public IList GetAllPortfolios() - { - throw new NotImplementedException(); - } - - public void SavePortfolio(Portfolio portfolio) - { - throw new NotImplementedException(); - } - - public void DeletePortfolioById(int portfolioId) - { - throw new NotImplementedException(); - } - - public Portfolio GetPortfolioById(long portfolioId) - { - throw new NotImplementedException(); - } - - public Portfolio GetPortfolioByName(string portfolioName) - { - throw new NotImplementedException(); - } - - public IList GetAllPositions(long portfolioId) - { - throw new NotImplementedException(); - } - - public void SavePosition(Position position) - { - throw new NotImplementedException(); - } - - public void DeletePositionById(long positionId) - { - throw new NotImplementedException(); - } - - public Position GetPositionById(long positionId) - { - throw new NotImplementedException(); + return IttyBittyIoC.Resolve(serviceType); } } } \ No newline at end of file diff --git a/MonoStockPortfolio/Framework/TinyIoC.cs b/MonoStockPortfolio/Framework/TinyIoC.cs deleted file mode 100644 index 160d6e6..0000000 --- a/MonoStockPortfolio/Framework/TinyIoC.cs +++ /dev/null @@ -1,2887 +0,0 @@ -//=============================================================================== -// TinyIoC -// -// An easy to use, hassle free, Inversion of Control Container for small projects -// and beginners alike. -// -// http://hg.grumpydev.com/tinyioc -//=============================================================================== -// Copyright © Steven Robbins. All rights reserved. -// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE. -//=============================================================================== - -#region Preprocessor Directives -// Uncomment this line if you want the container to automatically -// register the TinyMessenger messenger/event aggregator -//#define TINYMESSENGER - -// Preprocessor directives for enabling/disabling functionality -// depending on platform features. If the platform has an appropriate -// #DEFINE then these should be set automatically below. -#define EXPRESSIONS // Platform supports System.Linq.Expressions -#define APPDOMAIN_GETASSEMBLIES // Platform supports getting all assemblies from the AppDomain object -#define UNBOUND_GENERICS_GETCONSTRUCTORS // Platform supports GetConstructors on unbound generic types - -// CompactFramework -// By default does not support System.Linq.Expressions. -// AppDomain object does not support enumerating all assemblies in the app domain. -#if PocketPC || WINDOWS_PHONE -#undef EXPRESSIONS -#undef APPDOMAIN_GETASSEMBLIES -#undef UNBOUND_GENERICS_GETCONSTRUCTORS -#endif - -#if SILVERLIGHT -#undef APPDOMAIN_GETASSEMBLIES -#endif -#endregion -namespace TinyIoC -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Reflection; -#if EXPRESSIONS - using System.Linq.Expressions; -#endif - - #region SafeDictionary - public class SafeDictionary : IDisposable - { - private readonly object _Padlock = new object(); - private readonly Dictionary _Dictionary = new Dictionary(); - - public TValue this[TKey key] - { - set - { - lock (_Padlock) - { - TValue current; - if (_Dictionary.TryGetValue(key, out current)) - { - var disposable = current as IDisposable; - - if (disposable != null) - disposable.Dispose(); - } - - _Dictionary[key] = value; - } - } - } - - public bool TryGetValue(TKey key, out TValue value) - { - lock (_Padlock) - { - return _Dictionary.TryGetValue(key, out value); - } - } - - public bool Remove(TKey key) - { - lock (_Padlock) - { - return _Dictionary.Remove(key); - } - } - - public void Clear() - { - lock (_Padlock) - { - _Dictionary.Clear(); - } - } - - public IEnumerable Keys - { - get - { - return _Dictionary.Keys; - } - } - #region IDisposable Members - - public void Dispose() - { - lock (_Padlock) - { - var disposableItems = from item in _Dictionary.Values - where item is IDisposable - select item as IDisposable; - - foreach (var item in disposableItems) - { - item.Dispose(); - } - } - - GC.SuppressFinalize(this); - } - - #endregion - } - #endregion - - #region Extensions - public static class TypeExtensions - { - /// - /// Gets a generic method from a type given the method name, binding flags, generic types and parameter types - /// - /// Source type - /// Binding flags - /// Name of the method - /// Generic types to use to make the method generic - /// Method parameters - /// MethodInfo or null if no matches found - /// - /// - public static MethodInfo GetGenericMethod(this Type sourceType, System.Reflection.BindingFlags bindingFlags, string methodName, Type[] genericTypes, Type[] parameterTypes) - { - var methods = sourceType.GetMethods(bindingFlags) - .Where(mi => string.Equals(methodName, mi.Name, StringComparison.InvariantCulture)) - .Where(mi => mi.ContainsGenericParameters) - .Where(mi => mi.GetGenericArguments().Length == genericTypes.Length) - .Where(mi => mi.GetParameters().Length == parameterTypes.Length) - .Select(mi => mi.MakeGenericMethod(genericTypes)) - .Where(mi => mi.GetParameters().Select(pi => pi.ParameterType).SequenceEqual(parameterTypes)) - .ToList(); - - if (methods.Count > 1) - throw new AmbiguousMatchException(); - - var method = methods.FirstOrDefault(); - - return method; - } - } - #endregion - - #region TinyIoC Exception Types - public class TinyIoCResolutionException : Exception - { - private const string ERROR_TEXT = "Unable to resolve type: {0}"; - - public TinyIoCResolutionException(Type type) - : base(String.Format(ERROR_TEXT, type.FullName)) - { - } - - public TinyIoCResolutionException(Type type, Exception innerException) - : base(String.Format(ERROR_TEXT, type.FullName), innerException) - { - } - } - - public class TinyIoCRegistrationTypeException : Exception - { - private const string REGISTER_ERROR_TEXT = "Cannot register type {0} - abstract classes or interfaces are not valid implementation types for {1}."; - - public TinyIoCRegistrationTypeException(Type type, string factory) - : base(String.Format(REGISTER_ERROR_TEXT, type.FullName, factory)) - { - } - - public TinyIoCRegistrationTypeException(Type type, string factory, Exception innerException) - : base(String.Format(REGISTER_ERROR_TEXT, type.FullName, factory), innerException) - { - } - } - - public class TinyIoCRegistrationException : Exception - { - private const string CONVERT_ERROR_TEXT = "Cannot convert current registration of {0} to {1}"; - private const string GENERIC_CONSTRAINT_ERROR_TEXT = "Type {1} is not valid for a registration of type {0}"; - - public TinyIoCRegistrationException(Type type, string method) - : base(String.Format(CONVERT_ERROR_TEXT, type.FullName, method)) - { - } - - public TinyIoCRegistrationException(Type type, string method, Exception innerException) - : base(String.Format(CONVERT_ERROR_TEXT, type.FullName, method), innerException) - { - } - - public TinyIoCRegistrationException(Type registerType, Type implementationType) - : base(String.Format(GENERIC_CONSTRAINT_ERROR_TEXT, registerType.FullName, implementationType.FullName)) - { - } - - public TinyIoCRegistrationException(Type registerType, Type implementationType, Exception innerException) - : base(String.Format(GENERIC_CONSTRAINT_ERROR_TEXT, registerType.FullName, implementationType.FullName), innerException) - { - } - } - - public class TinyIoCWeakReferenceException : Exception - { - private const string ERROR_TEXT = "Unable to instantiate {0} - referenced object has been reclaimed"; - - public TinyIoCWeakReferenceException(Type type) - : base(String.Format(ERROR_TEXT, type.FullName)) - { - } - - public TinyIoCWeakReferenceException(Type type, Exception innerException) - : base(String.Format(ERROR_TEXT, type.FullName), innerException) - { - } - } - - public class TinyIoCConstructorResolutionException : Exception - { - private const string ERROR_TEXT = "Unable to resolve constructor for {0} using provided Expression."; - - public TinyIoCConstructorResolutionException(Type type) - : base(String.Format(ERROR_TEXT, type.FullName)) - { - } - - public TinyIoCConstructorResolutionException(Type type, Exception innerException) - : base(String.Format(ERROR_TEXT, type.FullName), innerException) - { - } - - public TinyIoCConstructorResolutionException(string message, Exception innerException) - : base(message, innerException) - { - } - - public TinyIoCConstructorResolutionException(string message) - : base(message) - { - } - } - - public class TinyIoCAutoRegistrationException : Exception - { - private const string ERROR_TEXT = "Duplicate implementation of type {0} found ({1})."; - - public TinyIoCAutoRegistrationException(Type registerType, IEnumerable types) - : base(String.Format(ERROR_TEXT, registerType, GetTypesString(types))) - { - } - - public TinyIoCAutoRegistrationException(Type registerType, IEnumerable types, Exception innerException) - : base(String.Format(ERROR_TEXT, registerType, GetTypesString(types)), innerException) - { - } - - private static string GetTypesString(IEnumerable types) - { - var typeNames = from type in types - select type.FullName; - - return string.Join(",", typeNames.ToArray()); - } - } - #endregion - - #region Public Setup / Settings Classes - /// - /// Name/Value pairs for specifying "user" parameters when resolving - /// - public sealed class NamedParameterOverloads : Dictionary - { - public static NamedParameterOverloads FromIDictionary(IDictionary data) - { - return data as NamedParameterOverloads ?? new NamedParameterOverloads(data); - } - - public NamedParameterOverloads() - { - } - - public NamedParameterOverloads(IDictionary data) - : base(data) - { - } - - private static readonly NamedParameterOverloads _Default = new NamedParameterOverloads(); - - public static NamedParameterOverloads Default - { - get - { - return _Default; - } - } - } - - public enum UnregisteredResolutionActions - { - /// - /// Attempt to resolve type, even if the type isn't registered. - /// - /// Registered types/options will always take precedence. - /// - AttemptResolve, - - /// - /// Fail resolution if type not explicitly registered - /// - Fail, - - /// - /// Attempt to resolve unregistered type if requested type is generic - /// and no registration exists for the specific generic parameters used. - /// - /// Registered types/options will always take precedence. - /// - GenericsOnly - } - - public enum NamedResolutionFailureActions - { - AttemptUnnamedResolution, - Fail - } - - /// - /// Resolution settings - /// - public sealed class ResolveOptions - { - private static readonly ResolveOptions _Default = new ResolveOptions(); - private static readonly ResolveOptions _FailUnregisteredAndNameNotFound = new ResolveOptions() { NamedResolutionFailureAction = NamedResolutionFailureActions.Fail, UnregisteredResolutionAction = UnregisteredResolutionActions.Fail }; - private static readonly ResolveOptions _FailUnregisteredOnly = new ResolveOptions() { NamedResolutionFailureAction = NamedResolutionFailureActions.AttemptUnnamedResolution, UnregisteredResolutionAction = UnregisteredResolutionActions.Fail }; - private static readonly ResolveOptions _FailNameNotFoundOnly = new ResolveOptions() { NamedResolutionFailureAction = NamedResolutionFailureActions.Fail, UnregisteredResolutionAction = UnregisteredResolutionActions.AttemptResolve }; - - private UnregisteredResolutionActions _UnregisteredResolutionAction = UnregisteredResolutionActions.AttemptResolve; - public UnregisteredResolutionActions UnregisteredResolutionAction - { - get { return _UnregisteredResolutionAction; } - set { _UnregisteredResolutionAction = value; } - } - - private NamedResolutionFailureActions _NamedResolutionFailureAction = NamedResolutionFailureActions.Fail; - public NamedResolutionFailureActions NamedResolutionFailureAction - { - get { return _NamedResolutionFailureAction; } - set { _NamedResolutionFailureAction = value; } - } - - /// - /// Gets the default options (attempt resolution of unregistered types, fail on named resolution if name not found) - /// - public static ResolveOptions Default - { - get - { - return _Default; - } - } - - /// - /// Preconfigured option for attempting resolution of unregistered types and failing on named resolution if name not found - /// - public static ResolveOptions FailNameNotFoundOnly - { - get - { - return _FailNameNotFoundOnly; - } - } - - /// - /// Preconfigured option for failing on resolving unregistered types and on named resolution if name not found - /// - public static ResolveOptions FailUnregisteredAndNameNotFound - { - get - { - return _FailUnregisteredAndNameNotFound; - } - } - - /// - /// Preconfigured option for failing on resolving unregistered types, but attempting unnamed resolution if name not found - /// - public static ResolveOptions FailUnregisteredOnly - { - get - { - return _FailUnregisteredOnly; - } - } - } - #endregion - - public sealed class TinyIoCContainer : IDisposable - { - #region "Fluent" API - /// - /// Registration options for "fluent" API - /// - public sealed class RegisterOptions - { - private TinyIoCContainer _Container; - private TypeRegistration _Registration; - - public RegisterOptions(TinyIoCContainer container, TypeRegistration registration) - { - _Container = container; - _Registration = registration; - } - - /// - /// Make registration a singleton (single instance) if possible - /// - /// RegisterOptions - /// - public RegisterOptions AsSingleton() - { - var currentFactory = _Container.GetCurrentFactory(_Registration); - - if (currentFactory == null) - throw new TinyIoCRegistrationException(_Registration.Type, "singleton"); - - return _Container.AddUpdateRegistration(_Registration, currentFactory.SingletonVariant); - } - - /// - /// Make registration multi-instance if possible - /// - /// RegisterOptions - /// - public RegisterOptions AsMultiInstance() - { - var currentFactory = _Container.GetCurrentFactory(_Registration); - - if (currentFactory == null) - throw new TinyIoCRegistrationException(_Registration.Type, "multi-instance"); - - return _Container.AddUpdateRegistration(_Registration, currentFactory.MultiInstanceVariant); - } - - /// - /// Make registration hold a weak reference if possible - /// - /// RegisterOptions - /// - public RegisterOptions WithWeakReference() - { - var currentFactory = _Container.GetCurrentFactory(_Registration); - - if (currentFactory == null) - throw new TinyIoCRegistrationException(_Registration.Type, "weak reference"); - - return _Container.AddUpdateRegistration(_Registration, currentFactory.WeakReferenceVariant); - } - - /// - /// Make registration hold a strong reference if possible - /// - /// RegisterOptions - /// - public RegisterOptions WithStrongReference() - { - var currentFactory = _Container.GetCurrentFactory(_Registration); - - if (currentFactory == null) - throw new TinyIoCRegistrationException(_Registration.Type, "strong reference"); - - return _Container.AddUpdateRegistration(_Registration, currentFactory.StrongReferenceVariant); - } - -#if EXPRESSIONS - public RegisterOptions UsingConstructor(Expression> constructor) - { - var lambda = constructor as LambdaExpression; - if (lambda == null) - throw new TinyIoCConstructorResolutionException(typeof(RegisterType)); - - var newExpression = lambda.Body as NewExpression; - if (newExpression == null) - throw new TinyIoCConstructorResolutionException(typeof(RegisterType)); - - var constructorInfo = newExpression.Constructor; - if (constructorInfo == null) - throw new TinyIoCConstructorResolutionException(typeof(RegisterType)); - - var currentFactory = _Container.GetCurrentFactory(_Registration); - if (currentFactory == null) - throw new TinyIoCConstructorResolutionException(typeof(RegisterType)); - - currentFactory.SetConstructor(constructorInfo); - - return this; - } -#endif - } - - /// - /// Registration options for "fluent" API when registering multiple implementations - /// - public sealed class MultiRegisterOptions - { - private IEnumerable _RegisterOptions; - - /// - /// Initializes a new instance of the MultiRegisterOptions class. - /// - /// Registration options - public MultiRegisterOptions(IEnumerable registerOptions) - { - _RegisterOptions = registerOptions; - } - - /// - /// Make registration a singleton (single instance) if possible - /// - /// RegisterOptions - /// - public MultiRegisterOptions AsSingleton() - { - _RegisterOptions = ExecuteOnAllRegisterOptions(ro => ro.AsSingleton()); - return this; - } - - /// - /// Make registration multi-instance if possible - /// - /// MultiRegisterOptions - /// - public MultiRegisterOptions AsMultiInstance() - { - _RegisterOptions = ExecuteOnAllRegisterOptions(ro => ro.AsMultiInstance()); - return this; - } - - private IEnumerable ExecuteOnAllRegisterOptions(Func action) - { - var newRegisterOptions = new List(); - - foreach (var registerOption in _RegisterOptions) - { - newRegisterOptions.Add(action(registerOption)); - } - - return newRegisterOptions; - } - } - #endregion - - #region Public API - #region Child Containers - public TinyIoCContainer GetChildContainer() - { - return new TinyIoCContainer(this); - } - #endregion - - #region Registration - /// - /// Attempt to automatically register all non-generic classes and interfaces in the current app domain. - /// - /// If more than one class implements an interface then only one implementation will be registered - /// although no error will be thrown. - /// - public void AutoRegister() - { -#if APPDOMAIN_GETASSEMBLIES - AutoRegisterInternal(AppDomain.CurrentDomain.GetAssemblies().Where(a => !IsIgnoredAssembly(a)), true); -#else - AutoRegisterInternal(new Assembly[] {this.GetType().Assembly}, true); -#endif - } - - /// - /// Attempt to automatically register all non-generic classes and interfaces in the current app domain. - /// - /// Whether to ignore duplicate implementations of an interface/base class. False=throw an exception - /// - public void AutoRegister(bool ignoreDuplicateImplementations) - { -#if APPDOMAIN_GETASSEMBLIES - AutoRegisterInternal(AppDomain.CurrentDomain.GetAssemblies().Where(a => !IsIgnoredAssembly(a)), ignoreDuplicateImplementations); -#else - AutoRegisterInternal(new Assembly[] { this.GetType().Assembly }, ignoreDuplicateImplementations); -#endif - } - - /// - /// Attempt to automatically register all non-generic classes and interfaces in the specified assembly - /// - /// If more than one class implements an interface then only one implementation will be registered - /// although no error will be thrown. - /// - /// Assembly to process - public void AutoRegister(Assembly assembly) - { - AutoRegisterInternal(new Assembly[] { assembly }, true); - } - - /// - /// Attempt to automatically register all non-generic classes and interfaces in the specified assembly - /// - /// Assembly to process - /// Whether to ignore duplicate implementations of an interface/base class. False=throw an exception - /// - public void AutoRegister(Assembly assembly, bool ignoreDuplicateImplementations) - { - AutoRegisterInternal(new Assembly[] { assembly }, ignoreDuplicateImplementations); - } - - /// - /// Attempt to automatically register all non-generic classes and interfaces in the specified assemblies - /// - /// If more than one class implements an interface then only one implementation will be registered - /// although no error will be thrown. - /// - /// Assemblies to process - public void AutoRegister(IEnumerable assemblies) - { - AutoRegisterInternal(assemblies, true); - } - - /// - /// Attempt to automatically register all non-generic classes and interfaces in the specified assemblies - /// - /// Assemblies to process - /// Whether to ignore duplicate implementations of an interface/base class. False=throw an exception - /// - public void AutoRegister(IEnumerable assemblies, bool ignoreDuplicateImplementations) - { - AutoRegisterInternal(assemblies, ignoreDuplicateImplementations); - } - - /// - /// Creates/replaces a container class registration with default options. - /// - /// Type to register - /// RegisterOptions for fluent API - public RegisterOptions Register(Type registerImplementation) - { - return ExecuteGenericRegister(new Type[] { registerImplementation }, new Type[] { }, null); - } - - /// - /// Creates/replaces a named container class registration with default options. - /// - /// Type to register - /// Name of registration - /// RegisterOptions for fluent API - public RegisterOptions Register(Type registerImplementation, string name) - { - return ExecuteGenericRegister(new Type[] { registerImplementation }, new Type[] { typeof(string) }, new object[] { name }); - } - - /// - /// Creates/replaces a container class registration with a given implementation and default options. - /// - /// Type to register - /// Type to instantiate that implements RegisterType - /// RegisterOptions for fluent API - public RegisterOptions Register(Type registerType, Type registerImplementation) - { - return ExecuteGenericRegister(new Type[] { registerType, registerImplementation }, new Type[] { }, null); - } - - /// - /// Creates/replaces a named container class registration with a given implementation and default options. - /// - /// Type to register - /// Type to instantiate that implements RegisterType - /// Name of registration - /// RegisterOptions for fluent API - public RegisterOptions Register(Type registerType, Type registerImplementation, string name) - { - return ExecuteGenericRegister(new Type[] { registerType, registerImplementation }, new Type[] { typeof(string) }, new object[] { name }); - } - - /// - /// Creates/replaces a container class registration with a specific, strong referenced, instance. - /// - /// Type to register - /// Instance of RegisterType to register - /// RegisterOptions for fluent API - public RegisterOptions Register(Type registerImplementation, object instance) - { - return ExecuteGenericRegister(new Type[] { registerImplementation }, new Type[] { registerImplementation }, new object[] { instance }); - } - - /// - /// Creates/replaces a named container class registration with a specific, strong referenced, instance. - /// - /// Type to register - /// Instance of RegisterType to register - /// Name of registration - /// RegisterOptions for fluent API - public RegisterOptions Register(Type registerImplementation, object instance, string name) - { - return ExecuteGenericRegister(new Type[] { registerImplementation }, new Type[] { registerImplementation, typeof(string) }, new object[] { instance, name }); - } - - /// - /// Creates/replaces a container class registration with a specific, strong referenced, instance. - /// - /// Type to register - /// Type of instance to register that implements RegisterType - /// Instance of RegisterImplementation to register - /// RegisterOptions for fluent API - public RegisterOptions Register(Type registerType, Type implementationType, object instance) - { - return ExecuteGenericRegister(new Type[] { registerType, implementationType }, new Type[] { implementationType }, new object[] { instance }); - } - - /// - /// Creates/replaces a named container class registration with a specific, strong referenced, instance. - /// - /// Type to register - /// Type of instance to register that implements RegisterType - /// Instance of RegisterImplementation to register - /// Name of registration - /// RegisterOptions for fluent API - public RegisterOptions Register(Type registerType, Type implementationType, object instance, string name) - { - return ExecuteGenericRegister(new Type[] { registerType, implementationType }, new Type[] { implementationType, typeof(string) }, new object[] { instance, name }); - } - - /// - /// Creates/replaces a container class registration with default options. - /// - /// Type to register - /// RegisterOptions for fluent API - public RegisterOptions Register() - where RegisterType : class - { - return RegisterInternal(typeof(RegisterType), string.Empty, GetDefaultObjectFactory()); - } - - /// - /// Creates/replaces a named container class registration with default options. - /// - /// Type to register - /// Name of registration - /// RegisterOptions for fluent API - public RegisterOptions Register(string name) - where RegisterType : class - { - return RegisterInternal(typeof(RegisterType), name, GetDefaultObjectFactory()); - } - - /// - /// Creates/replaces a container class registration with a given implementation and default options. - /// - /// Type to register - /// Type to instantiate that implements RegisterType - /// RegisterOptions for fluent API - public RegisterOptions Register() - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - return RegisterInternal(typeof(RegisterType), string.Empty, GetDefaultObjectFactory()); - } - - /// - /// Creates/replaces a named container class registration with a given implementation and default options. - /// - /// Type to register - /// Type to instantiate that implements RegisterType - /// Name of registration - /// RegisterOptions for fluent API - public RegisterOptions Register(string name) - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - return RegisterInternal(typeof(RegisterType), name, GetDefaultObjectFactory()); - } - - /// - /// Creates/replaces a container class registration with a specific, strong referenced, instance. - /// - /// Type to register - /// Instance of RegisterType to register - /// RegisterOptions for fluent API - public RegisterOptions Register(RegisterType instance) - where RegisterType : class - { - return RegisterInternal(typeof(RegisterType), string.Empty, new InstanceFactory(instance)); - } - - /// - /// Creates/replaces a named container class registration with a specific, strong referenced, instance. - /// - /// Type to register - /// Instance of RegisterType to register - /// Name of registration - /// RegisterOptions for fluent API - public RegisterOptions Register(RegisterType instance, string name) - where RegisterType : class - { - return RegisterInternal(typeof(RegisterType), name, new InstanceFactory(instance)); - } - - /// - /// Creates/replaces a container class registration with a specific, strong referenced, instance. - /// - /// Type to register - /// Type of instance to register that implements RegisterType - /// Instance of RegisterImplementation to register - /// RegisterOptions for fluent API - public RegisterOptions Register(RegisterImplementation instance) - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - return RegisterInternal(typeof(RegisterType), string.Empty, new InstanceFactory(instance)); - } - - /// - /// Creates/replaces a named container class registration with a specific, strong referenced, instance. - /// - /// Type to register - /// Type of instance to register that implements RegisterType - /// Instance of RegisterImplementation to register - /// Name of registration - /// RegisterOptions for fluent API - public RegisterOptions Register(RegisterImplementation instance, string name) - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - return RegisterInternal(typeof(RegisterType), name, new InstanceFactory(instance)); - } - - /// - /// Creates/replaces a container class registration with a user specified factory - /// - /// Type to register - /// Factory/lambda that returns an instance of RegisterType - /// RegisterOptions for fluent API - public RegisterOptions Register(Func factory) - where RegisterType : class - { - return RegisterInternal(typeof(RegisterType), string.Empty, new DelegateFactory(factory)); - } - - /// - /// Creates/replaces a named container class registration with a user specified factory - /// - /// Type to register - /// Factory/lambda that returns an instance of RegisterType - /// Name of registation - /// RegisterOptions for fluent API - public RegisterOptions Register(Func factory, string name) - where RegisterType : class - { - return RegisterInternal(typeof(RegisterType), name, new DelegateFactory(factory)); - } - - /// - /// Register multiple implementations of a type. - /// - /// Internally this registers each implementation using the full name of the class as its registration name. - /// - /// Type that each implementation implements - /// Types that implement RegisterType - /// MultiRegisterOptions for the fluent API - public MultiRegisterOptions RegisterMultiple(IEnumerable types) - { - if (types == null) - throw new ArgumentNullException("types", "types is null."); - - foreach (var type in types) - if (!typeof(RegisterType).IsAssignableFrom(type)) - throw new ArgumentException(String.Format("types: The type {0} is not assignable from {1}", typeof(RegisterType).FullName, type.FullName)); - - if (types.Count() != types.Distinct().Count()) - throw new ArgumentException("types: The same implementation type cannot be specificed multiple times"); - - var registerOptions = new List(); - - foreach (var type in types) - { - registerOptions.Add(Register(typeof(RegisterType), type, type.FullName)); - } - - return new MultiRegisterOptions(registerOptions); - } - #endregion - - #region Resolution - /// - /// Attempts to resolve a type using default options. - /// - /// Type to resolve - /// Instance of type - /// Unable to resolve the type. - public object Resolve(Type resolveType) - { - return ResolveInternal(new TypeRegistration(resolveType), NamedParameterOverloads.Default, ResolveOptions.Default); - } - - /// - /// Attempts to resolve a type using specified options. - /// - /// Type to resolve - /// Resolution options - /// Instance of type - /// Unable to resolve the type. - public object Resolve(Type resolveType, ResolveOptions options) - { - return ResolveInternal(new TypeRegistration(resolveType), NamedParameterOverloads.Default, options); - } - - /// - /// Attempts to resolve a type using default options and the supplied name. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// Name of registration - /// Instance of type - /// Unable to resolve the type. - public object Resolve(Type resolveType, string name) - { - return ResolveInternal(new TypeRegistration(resolveType, name), NamedParameterOverloads.Default, ResolveOptions.Default); - } - - /// - /// Attempts to resolve a type using supplied options and name. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// Name of registration - /// Resolution options - /// Instance of type - /// Unable to resolve the type. - public object Resolve(Type resolveType, string name, ResolveOptions options) - { - return ResolveInternal(new TypeRegistration(resolveType, name), NamedParameterOverloads.Default, options); - } - - /// - /// Attempts to resolve a type using default options and the supplied constructor parameters. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// User specified constructor parameters - /// Instance of type - /// Unable to resolve the type. - public object Resolve(Type resolveType, NamedParameterOverloads parameters) - { - return ResolveInternal(new TypeRegistration(resolveType), parameters, ResolveOptions.Default); - } - - /// - /// Attempts to resolve a type using specified options and the supplied constructor parameters. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// User specified constructor parameters - /// Resolution options - /// Instance of type - /// Unable to resolve the type. - public object Resolve(Type resolveType, NamedParameterOverloads parameters, ResolveOptions options) - { - return ResolveInternal(new TypeRegistration(resolveType), parameters, options); - } - - /// - /// Attempts to resolve a type using default options and the supplied constructor parameters and name. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// User specified constructor parameters - /// Name of registration - /// Instance of type - /// Unable to resolve the type. - public object Resolve(Type resolveType, string name, NamedParameterOverloads parameters) - { - return ResolveInternal(new TypeRegistration(resolveType, name), parameters, ResolveOptions.Default); - } - - /// - /// Attempts to resolve a named type using specified options and the supplied constructor parameters. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// Name of registration - /// User specified constructor parameters - /// Resolution options - /// Instance of type - /// Unable to resolve the type. - public object Resolve(Type resolveType, string name, NamedParameterOverloads parameters, ResolveOptions options) - { - return ResolveInternal(new TypeRegistration(resolveType, name), parameters, options); - } - - /// - /// Attempts to resolve a type using default options. - /// - /// Type to resolve - /// Instance of type - /// Unable to resolve the type. - public ResolveType Resolve() - where ResolveType : class - { - return (ResolveType)Resolve(typeof(ResolveType)); - } - - /// - /// Attempts to resolve a type using specified options. - /// - /// Type to resolve - /// Resolution options - /// Instance of type - /// Unable to resolve the type. - public ResolveType Resolve(ResolveOptions options) - where ResolveType : class - { - return (ResolveType)Resolve(typeof(ResolveType), options); - } - - /// - /// Attempts to resolve a type using default options and the supplied name. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// Name of registration - /// Instance of type - /// Unable to resolve the type. - public ResolveType Resolve(string name) - where ResolveType : class - { - return (ResolveType)Resolve(typeof(ResolveType), name); - } - - /// - /// Attempts to resolve a type using supplied options and name. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// Name of registration - /// Resolution options - /// Instance of type - /// Unable to resolve the type. - public ResolveType Resolve(string name, ResolveOptions options) - where ResolveType : class - { - return (ResolveType)Resolve(typeof(ResolveType), name, options); - } - - /// - /// Attempts to resolve a type using default options and the supplied constructor parameters. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// User specified constructor parameters - /// Instance of type - /// Unable to resolve the type. - public ResolveType Resolve(NamedParameterOverloads parameters) - where ResolveType : class - { - return (ResolveType)Resolve(typeof(ResolveType), parameters); - } - - /// - /// Attempts to resolve a type using specified options and the supplied constructor parameters. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// User specified constructor parameters - /// Resolution options - /// Instance of type - /// Unable to resolve the type. - public ResolveType Resolve(NamedParameterOverloads parameters, ResolveOptions options) - where ResolveType : class - { - return (ResolveType)Resolve(typeof(ResolveType), parameters, options); - } - - /// - /// Attempts to resolve a type using default options and the supplied constructor parameters and name. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// User specified constructor parameters - /// Name of registration - /// Instance of type - /// Unable to resolve the type. - public ResolveType Resolve(string name, NamedParameterOverloads parameters) - where ResolveType : class - { - return (ResolveType)Resolve(typeof(ResolveType), name, parameters); - } - - /// - /// Attempts to resolve a named type using specified options and the supplied constructor parameters. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Type to resolve - /// Name of registration - /// User specified constructor parameters - /// Resolution options - /// Instance of type - /// Unable to resolve the type. - public ResolveType Resolve(string name, NamedParameterOverloads parameters, ResolveOptions options) - where ResolveType : class - { - return (ResolveType)Resolve(typeof(ResolveType), name, parameters, options); - } - - /// - /// Attempts to predict whether a given type can be resolved with default options. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// Bool indicating whether the type can be resolved - public bool CanResolve(Type resolveType) - { - return CanResolveInternal(new TypeRegistration(resolveType), NamedParameterOverloads.Default, ResolveOptions.Default); - } - - /// - /// Attempts to predict whether a given named type can be resolved with default options. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Bool indicating whether the type can be resolved - private bool CanResolve(Type resolveType, string name) - { - return CanResolveInternal(new TypeRegistration(resolveType, name), NamedParameterOverloads.Default, ResolveOptions.Default); - } - - /// - /// Attempts to predict whether a given type can be resolved with the specified options. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// Resolution options - /// Bool indicating whether the type can be resolved - public bool CanResolve(Type resolveType, ResolveOptions options) - { - return CanResolveInternal(new TypeRegistration(resolveType), NamedParameterOverloads.Default, options); - } - - /// - /// Attempts to predict whether a given named type can be resolved with the specified options. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// Resolution options - /// Bool indicating whether the type can be resolved - public bool CanResolve(Type resolveType, string name, ResolveOptions options) - { - return CanResolveInternal(new TypeRegistration(resolveType, name), NamedParameterOverloads.Default, options); - } - - /// - /// Attempts to predict whether a given type can be resolved with the supplied constructor parameters and default options. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// User supplied named parameter overloads - /// Bool indicating whether the type can be resolved - public bool CanResolve(Type resolveType, NamedParameterOverloads parameters) - { - return CanResolveInternal(new TypeRegistration(resolveType), parameters, ResolveOptions.Default); - } - - /// - /// Attempts to predict whether a given named type can be resolved with the supplied constructor parameters and default options. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// User supplied named parameter overloads - /// Bool indicating whether the type can be resolved - public bool CanResolve(Type resolveType, string name, NamedParameterOverloads parameters) - { - return CanResolveInternal(new TypeRegistration(resolveType, name), parameters, ResolveOptions.Default); - } - - /// - /// Attempts to predict whether a given type can be resolved with the supplied constructor parameters options. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// User supplied named parameter overloads - /// Resolution options - /// Bool indicating whether the type can be resolved - public bool CanResolve(Type resolveType, NamedParameterOverloads parameters, ResolveOptions options) - { - return CanResolveInternal(new TypeRegistration(resolveType), parameters, options); - } - - /// - /// Attempts to predict whether a given named type can be resolved with the supplied constructor parameters options. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// User supplied named parameter overloads - /// Resolution options - /// Bool indicating whether the type can be resolved - public bool CanResolve(Type resolveType, string name, NamedParameterOverloads parameters, ResolveOptions options) - { - return CanResolveInternal(new TypeRegistration(resolveType, name), parameters, options); - } - - /// - /// Attempts to predict whether a given type can be resolved with default options. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// Bool indicating whether the type can be resolved - public bool CanResolve() - where ResolveType : class - { - return CanResolve(typeof(ResolveType)); - } - - /// - /// Attempts to predict whether a given named type can be resolved with default options. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Bool indicating whether the type can be resolved - public bool CanResolve(string name) - where ResolveType : class - { - return CanResolve(typeof(ResolveType), name); - } - - /// - /// Attempts to predict whether a given type can be resolved with the specified options. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// Resolution options - /// Bool indicating whether the type can be resolved - public bool CanResolve(ResolveOptions options) - where ResolveType : class - { - return CanResolve(typeof(ResolveType), options); - } - - /// - /// Attempts to predict whether a given named type can be resolved with the specified options. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// Resolution options - /// Bool indicating whether the type can be resolved - public bool CanResolve(string name, ResolveOptions options) - where ResolveType : class - { - return CanResolve(typeof(ResolveType), name, options); - } - - /// - /// Attempts to predict whether a given type can be resolved with the supplied constructor parameters and default options. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// User supplied named parameter overloads - /// Bool indicating whether the type can be resolved - public bool CanResolve(NamedParameterOverloads parameters) - where ResolveType : class - { - return CanResolve(typeof(ResolveType), parameters); - } - - /// - /// Attempts to predict whether a given named type can be resolved with the supplied constructor parameters and default options. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// User supplied named parameter overloads - /// Bool indicating whether the type can be resolved - public bool CanResolve(string name, NamedParameterOverloads parameters) - where ResolveType : class - { - return CanResolve(typeof(ResolveType), name, parameters); - } - - /// - /// Attempts to predict whether a given type can be resolved with the supplied constructor parameters options. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// User supplied named parameter overloads - /// Resolution options - /// Bool indicating whether the type can be resolved - public bool CanResolve(NamedParameterOverloads parameters, ResolveOptions options) - where ResolveType : class - { - return CanResolve(typeof(ResolveType), parameters, options); - } - - /// - /// Attempts to predict whether a given named type can be resolved with the supplied constructor parameters options. - /// - /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists). - /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail. - /// - /// Note: Resolution may still fail if user defined factory registations fail to construct objects when called. - /// - /// Type to resolve - /// Name of registration - /// User supplied named parameter overloads - /// Resolution options - /// Bool indicating whether the type can be resolved - public bool CanResolve(string name, NamedParameterOverloads parameters, ResolveOptions options) - where ResolveType : class - { - return CanResolve(typeof(ResolveType), name, parameters, options); - } - - /// - /// Attemps to resolve a type using the default options - /// - /// Type to resolve - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(Type resolveType, out object resolvedType) - { - try - { - resolvedType = Resolve(resolveType); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = null; - return false; - } - } - - /// - /// Attemps to resolve a type using the given options - /// - /// Type to resolve - /// Resolution options - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(Type resolveType, ResolveOptions options, out object resolvedType) - { - try - { - resolvedType = Resolve(resolveType, options); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = null; - return false; - } - } - - /// - /// Attemps to resolve a type using the default options and given name - /// - /// Type to resolve - /// Name of registration - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(Type resolveType, string name, out object resolvedType) - { - try - { - resolvedType = Resolve(resolveType, name); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = null; - return false; - } - } - - /// - /// Attemps to resolve a type using the given options and name - /// - /// Type to resolve - /// Name of registration - /// Resolution options - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(Type resolveType, string name, ResolveOptions options, out object resolvedType) - { - try - { - resolvedType = Resolve(resolveType, name, options); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = null; - return false; - } - } - - /// - /// Attemps to resolve a type using the default options and supplied constructor parameters - /// - /// Type to resolve - /// User specified constructor parameters - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(Type resolveType, NamedParameterOverloads parameters, out object resolvedType) - { - try - { - resolvedType = Resolve(resolveType, parameters); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = null; - return false; - } - } - - /// - /// Attemps to resolve a type using the default options and supplied name and constructor parameters - /// - /// Type to resolve - /// Name of registration - /// User specified constructor parameters - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(Type resolveType, string name, NamedParameterOverloads parameters, out object resolvedType) - { - try - { - resolvedType = Resolve(resolveType, name, parameters); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = null; - return false; - } - } - - /// - /// Attemps to resolve a type using the supplied options and constructor parameters - /// - /// Type to resolve - /// Name of registration - /// User specified constructor parameters - /// Resolution options - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(Type resolveType, NamedParameterOverloads parameters, ResolveOptions options, out object resolvedType) - { - try - { - resolvedType = Resolve(resolveType, parameters, options); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = null; - return false; - } - } - - /// - /// Attemps to resolve a type using the supplied name, options and constructor parameters - /// - /// Type to resolve - /// Name of registration - /// User specified constructor parameters - /// Resolution options - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(Type resolveType, string name, NamedParameterOverloads parameters, ResolveOptions options, out object resolvedType) - { - try - { - resolvedType = Resolve(resolveType, name, parameters, options); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = null; - return false; - } - } - - /// - /// Attemps to resolve a type using the default options - /// - /// Type to resolve - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(out ResolveType resolvedType) - where ResolveType : class - { - try - { - resolvedType = Resolve(); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = default(ResolveType); - return false; - } - } - - /// - /// Attemps to resolve a type using the given options - /// - /// Type to resolve - /// Resolution options - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(ResolveOptions options, out ResolveType resolvedType) - where ResolveType : class - { - try - { - resolvedType = Resolve(options); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = default(ResolveType); - return false; - } - } - - /// - /// Attemps to resolve a type using the default options and given name - /// - /// Type to resolve - /// Name of registration - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(string name, out ResolveType resolvedType) - where ResolveType : class - { - try - { - resolvedType = Resolve(name); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = default(ResolveType); - return false; - } - } - - /// - /// Attemps to resolve a type using the given options and name - /// - /// Type to resolve - /// Name of registration - /// Resolution options - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(string name, ResolveOptions options, out ResolveType resolvedType) - where ResolveType : class - { - try - { - resolvedType = Resolve(name, options); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = default(ResolveType); - return false; - } - } - - /// - /// Attemps to resolve a type using the default options and supplied constructor parameters - /// - /// Type to resolve - /// User specified constructor parameters - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(NamedParameterOverloads parameters, out ResolveType resolvedType) - where ResolveType : class - { - try - { - resolvedType = Resolve(parameters); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = default(ResolveType); - return false; - } - } - - /// - /// Attemps to resolve a type using the default options and supplied name and constructor parameters - /// - /// Type to resolve - /// Name of registration - /// User specified constructor parameters - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(string name, NamedParameterOverloads parameters, out ResolveType resolvedType) - where ResolveType : class - { - try - { - resolvedType = Resolve(name, parameters); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = default(ResolveType); - return false; - } - } - - /// - /// Attemps to resolve a type using the supplied options and constructor parameters - /// - /// Type to resolve - /// Name of registration - /// User specified constructor parameters - /// Resolution options - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(NamedParameterOverloads parameters, ResolveOptions options, out ResolveType resolvedType) - where ResolveType : class - { - try - { - resolvedType = Resolve(parameters, options); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = default(ResolveType); - return false; - } - } - - /// - /// Attemps to resolve a type using the supplied name, options and constructor parameters - /// - /// Type to resolve - /// Name of registration - /// User specified constructor parameters - /// Resolution options - /// Resolved type or default if resolve fails - /// True if resolved sucessfully, false otherwise - public bool TryResolve(string name, NamedParameterOverloads parameters, ResolveOptions options, out ResolveType resolvedType) - where ResolveType : class - { - try - { - resolvedType = Resolve(name, parameters, options); - return true; - } - catch (TinyIoCResolutionException) - { - resolvedType = default(ResolveType); - return false; - } - } - - /// - /// Returns all registrations of a type - /// - /// Type to resolveAll - /// Whether to include un-named (default) registrations - /// IEnumerable - public IEnumerable ResolveAll(Type resolveType, bool includeUnnamed) - { - return ResolveAllInternal(resolveType, includeUnnamed).Select(o => o); - } - - /// - /// Returns all registrations of a type, both named and unnamed - /// - /// Type to resolveAll - /// IEnumerable - public IEnumerable ResolveAll(Type resolveType) - { - return ResolveAll(resolveType, false); - } - - /// - /// Returns all registrations of a type - /// - /// Type to resolveAll - /// Whether to include un-named (default) registrations - /// IEnumerable - public IEnumerable ResolveAll(bool includeUnnamed) - where ResolveType : class - { - foreach (var resolvedType in ResolveAll(typeof(ResolveType), includeUnnamed)) - { - yield return resolvedType as ResolveType; - } - } - - /// - /// Returns all registrations of a type, both named and unnamed - /// - /// Type to resolveAll - /// Whether to include un-named (default) registrations - /// IEnumerable - public IEnumerable ResolveAll() - where ResolveType : class - { - return ResolveAll(true); - } - - /// - /// Attempts to resolve all public property dependencies on the given object. - /// - /// Object to "build up" - public void BuildUp(object input) - { - BuildUpInternal(input, ResolveOptions.Default); - } - - /// - /// Attempts to resolve all public property dependencies on the given object using the given resolve options. - /// - /// Object to "build up" - /// Resolve options to use - public void BuildUp(object input, ResolveOptions resolveOptions) - { - BuildUpInternal(input, resolveOptions); - } - #endregion - #endregion - - #region Object Factories - private abstract class ObjectFactoryBase - { - /// - /// Whether to assume this factory sucessfully constructs its objects - /// - /// Generally set to true for delegate style factories as CanResolve cannot delve - /// into the delegates they contain. - /// - public virtual bool AssumeConstruction { get { return false; } } - - /// - /// The type the factory instantiates - /// - public abstract Type CreatesType { get; } - - /// - /// Constructor to use, if specified - /// - public ConstructorInfo Constructor { get; protected set; } - - /// - /// Create the type - /// - /// Container that requested the creation - /// Any user parameters passed - /// - public abstract object GetObject(TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options); - - public virtual ObjectFactoryBase SingletonVariant - { - get - { - throw new TinyIoCRegistrationException(this.GetType(), "singleton"); - } - } - - public virtual ObjectFactoryBase MultiInstanceVariant - { - get - { - throw new TinyIoCRegistrationException(this.GetType(), "multi-instance"); - } - } - - public virtual ObjectFactoryBase StrongReferenceVariant - { - get - { - throw new TinyIoCRegistrationException(this.GetType(), "strong reference"); - } - } - - public virtual ObjectFactoryBase WeakReferenceVariant - { - get - { - throw new TinyIoCRegistrationException(this.GetType(), "weak reference"); - } - } - - public virtual void SetConstructor(ConstructorInfo constructor) - { - Constructor = constructor; - } - } - - /// - /// IObjectFactory that creates new instances of types for each resolution - /// - /// Registered type - /// Type to construct to fullful request for RegisteredType - private class MultiInstanceFactory : ObjectFactoryBase - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - public override Type CreatesType { get { return typeof(RegisterImplementation); } } - - public MultiInstanceFactory() - { - if (typeof(RegisterImplementation).IsAbstract || typeof(RegisterImplementation).IsInterface) - throw new TinyIoCRegistrationTypeException(typeof(RegisterImplementation), "MultiInstanceFactory"); - } - - public override object GetObject(TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options) - { - try - { - return container.ConstructType(typeof(RegisterImplementation), Constructor, parameters, options); - } - catch (TinyIoCResolutionException ex) - { - throw new TinyIoCResolutionException(typeof(RegisterImplementation), ex); - } - } - - public override ObjectFactoryBase SingletonVariant - { - get - { - return new SingletonFactory(); - } - } - - public override ObjectFactoryBase MultiInstanceVariant - { - get - { - return this; - } - } - } - - /// - /// IObjectFactory that invokes a specified delegate to construct the object - /// - /// Registered type to be constructed - private class DelegateFactory : ObjectFactoryBase - where RegisterType : class - { - private Func _factory; - - public override bool AssumeConstruction { get { return true; } } - - public override Type CreatesType { get { return typeof(RegisterType); } } - - public override object GetObject(TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options) - { - try - { - return _factory.Invoke(container, parameters); - } - catch (Exception ex) - { - throw new TinyIoCResolutionException(typeof(RegisterType), ex); - } - } - - public DelegateFactory(Func factory) - { - if (factory == null) - throw new ArgumentNullException("factory"); - - _factory = factory; - } - - public override ObjectFactoryBase WeakReferenceVariant - { - get - { - return new WeakDelegateFactory(_factory); - } - } - - public override ObjectFactoryBase StrongReferenceVariant - { - get - { - return this; - } - } - - public override void SetConstructor(ConstructorInfo constructor) - { - throw new TinyIoCConstructorResolutionException("Constructor selection is not possible for delegate factory registrations"); - } - } - - /// - /// IObjectFactory that invokes a specified delegate to construct the object - /// - /// Holds the delegate using a weak reference - /// - /// Registered type to be constructed - private class WeakDelegateFactory : ObjectFactoryBase - where RegisterType : class - { - private WeakReference _factory; - - public override bool AssumeConstruction { get { return true; } } - - public override Type CreatesType { get { return typeof(RegisterType); } } - - public override object GetObject(TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options) - { - var factory = _factory.Target as Func; - - if (factory == null) - throw new TinyIoCWeakReferenceException(typeof(RegisterType)); - - try - { - return factory.Invoke(container, parameters); - } - catch (Exception ex) - { - throw new TinyIoCResolutionException(typeof(RegisterType), ex); - } - } - - public WeakDelegateFactory(Func factory) - { - if (factory == null) - throw new ArgumentNullException("factory"); - - _factory = new WeakReference(factory); - } - - public override ObjectFactoryBase StrongReferenceVariant - { - get - { - var factory = _factory.Target as Func; - - if (factory == null) - throw new TinyIoCWeakReferenceException(typeof(RegisterType)); - - return new DelegateFactory(factory); - } - } - - public override ObjectFactoryBase WeakReferenceVariant - { - get - { - return this; - } - } - - public override void SetConstructor(ConstructorInfo constructor) - { - throw new TinyIoCConstructorResolutionException("Constructor selection is not possible for delegate factory registrations"); - } - } - - /// - /// Stores an particular instance to return for a type - /// - /// Registered type - /// Type of the instance - private class InstanceFactory : ObjectFactoryBase, IDisposable - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - private RegisterImplementation _instance; - - public override bool AssumeConstruction { get { return true; } } - - public InstanceFactory(RegisterImplementation instance) - { - _instance = instance; - } - - public override Type CreatesType - { - get { return typeof(RegisterImplementation); } - } - - public override object GetObject(TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options) - { - return _instance; - } - - public override ObjectFactoryBase MultiInstanceVariant - { - get - { - return new MultiInstanceFactory(); - } - } - - public override ObjectFactoryBase WeakReferenceVariant - { - get - { - return new WeakInstanceFactory(_instance); - } - } - - public override ObjectFactoryBase StrongReferenceVariant - { - get - { - return this; - } - } - - public override void SetConstructor(ConstructorInfo constructor) - { - throw new TinyIoCConstructorResolutionException("Constructor selection is not possible for instance factory registrations"); - } - - public void Dispose() - { - var disposable = _instance as IDisposable; - - if (disposable != null) - disposable.Dispose(); - } - } - - /// - /// Stores an particular instance to return for a type - /// - /// Stores the instance with a weak reference - /// - /// Registered type - /// Type of the instance - private class WeakInstanceFactory : ObjectFactoryBase, IDisposable - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - private WeakReference _instance; - - public WeakInstanceFactory(RegisterImplementation instance) - { - _instance = new WeakReference(instance); - } - - public override Type CreatesType - { - get { return typeof(RegisterImplementation); } - } - - public override object GetObject(TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options) - { - var instance = _instance.Target as RegisterImplementation; - - if (instance == null) - throw new TinyIoCWeakReferenceException(typeof(RegisterType)); - - return instance; - } - - public override ObjectFactoryBase MultiInstanceVariant - { - get - { - return new MultiInstanceFactory(); - } - } - - public override ObjectFactoryBase WeakReferenceVariant - { - get - { - return this; - } - } - - public override ObjectFactoryBase StrongReferenceVariant - { - get - { - var instance = _instance.Target as RegisterImplementation; - - if (instance == null) - throw new TinyIoCWeakReferenceException(typeof(RegisterType)); - - return new InstanceFactory(instance); - } - } - - public override void SetConstructor(ConstructorInfo constructor) - { - throw new TinyIoCConstructorResolutionException("Constructor selection is not possible for instance factory registrations"); - } - - public void Dispose() - { - var disposable = _instance.Target as IDisposable; - - if (disposable != null) - disposable.Dispose(); - } - } - - /// - /// A factory that lazy instantiates a type and always returns the same instance - /// - /// Registered type - /// Type to instantiate - private class SingletonFactory : ObjectFactoryBase, IDisposable - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - private readonly object SingletonLock = new object(); - private RegisterImplementation _Current; - - public SingletonFactory() - { - if (typeof(RegisterImplementation).IsAbstract || typeof(RegisterImplementation).IsInterface) - throw new TinyIoCRegistrationTypeException(typeof(RegisterImplementation), "SingletonFactory"); - } - - public override Type CreatesType - { - get { return typeof(RegisterImplementation); } - } - - public override object GetObject(TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options) - { - if (parameters.Count != 0) - throw new ArgumentException("Cannot specify parameters for singleton types"); - - lock (SingletonLock) - if (_Current == null) - _Current = container.ConstructType(typeof(RegisterImplementation), Constructor, options) as RegisterImplementation; - - return _Current; - } - - public override ObjectFactoryBase SingletonVariant - { - get - { - return this; - } - } - - public override ObjectFactoryBase MultiInstanceVariant - { - get - { - return new MultiInstanceFactory(); - } - } - - public void Dispose() - { - if (_Current != null) - { - var disposable = _Current as IDisposable; - - if (disposable != null) - disposable.Dispose(); - } - } - } - #endregion - - #region Singleton Container - private static readonly TinyIoCContainer _Current = new TinyIoCContainer(); - - static TinyIoCContainer() - { - } - - /// - /// Lazy created Singleton instance of the container for simple scenarios - /// - public static TinyIoCContainer Current - { - get - { - return _Current; - } - } - #endregion - - #region Type Registrations - public sealed class TypeRegistration - { - public Type Type { get; private set; } - public string Name { get; private set; } - - public TypeRegistration(Type type) - : this(type, string.Empty) - { - } - - public TypeRegistration(Type type, string name) - { - Type = type; - Name = name; - } - - public override bool Equals(object obj) - { - var typeRegistration = obj as TypeRegistration; - - if (typeRegistration == null) - return false; - - if (Type != typeRegistration.Type) - return false; - - if (String.Compare(Name, typeRegistration.Name, StringComparison.Ordinal) != 0) - return false; - - return true; - } - - public override int GetHashCode() - { - return String.Format("{0}|{1}", Type.FullName, Name).GetHashCode(); - } - } - private readonly SafeDictionary _RegisteredTypes; - #endregion - - #region Constructors - public TinyIoCContainer() - { - _RegisteredTypes = new SafeDictionary(); - - RegisterDefaultTypes(); - } - - TinyIoCContainer _Parent; - private TinyIoCContainer(TinyIoCContainer parent) - : this() - { - _Parent = parent; - } - #endregion - - #region Internal Methods - private readonly object _AutoRegisterLock = new object(); - private void AutoRegisterInternal(IEnumerable assemblies, bool ignoreDuplicateImplementations) - { - lock (_AutoRegisterLock) - { - var defaultFactoryMethod = this.GetType().GetMethod("GetDefaultObjectFactory", BindingFlags.NonPublic | BindingFlags.Instance); - - var types = assemblies.SelectMany(a => a.GetTypes()).Where(t => !IsIgnoredType(t)).ToList(); - - var concreteTypes = from type in types - where (type.IsClass == true) && (type.IsAbstract == false) && (type != this.GetType() && (type.DeclaringType != this.GetType()) && (!type.IsGenericTypeDefinition)) - select type; - - foreach (var type in concreteTypes) - { - Type[] genericTypes = { type, type }; - var genericDefaultFactoryMethod = defaultFactoryMethod.MakeGenericMethod(genericTypes); - try - { - RegisterInternal(type, string.Empty, genericDefaultFactoryMethod.Invoke(this, null) as ObjectFactoryBase); - } - catch (MethodAccessException) - { - // Ignore methods we can't access - added for Silverlight - } - } - - var abstractInterfaceTypes = from type in types - where ((type.IsInterface == true || type.IsAbstract == true) && (type.DeclaringType != this.GetType()) && (!type.IsGenericTypeDefinition)) - select type; - - foreach (var type in abstractInterfaceTypes) - { - var implementations = from implementationType in concreteTypes - where implementationType.GetInterfaces().Contains(type) || implementationType.BaseType == type - select implementationType; - - if (!ignoreDuplicateImplementations && implementations.Count() > 1) - throw new TinyIoCAutoRegistrationException(type, implementations); - - var firstImplementation = implementations.FirstOrDefault(); - if (firstImplementation != null) - { - Type[] genericTypes = { type, firstImplementation }; - var genericDefaultFactoryMethod = defaultFactoryMethod.MakeGenericMethod(genericTypes); - try - { - RegisterInternal(type, string.Empty, genericDefaultFactoryMethod.Invoke(this, null) as ObjectFactoryBase); - } - catch (MethodAccessException) - { - // Ignore methods we can't access - added for Silverlight - } - } - } - } - } - - private bool IsIgnoredAssembly(Assembly assembly) - { - // TODO - find a better way to remove "system" assemblies from the auto registration - var ignoreChecks = new List>() - { - asm => asm.FullName.StartsWith("Microsoft.", StringComparison.InvariantCulture), - asm => asm.FullName.StartsWith("System.", StringComparison.InvariantCulture), - asm => asm.FullName.StartsWith("System,", StringComparison.InvariantCulture), - asm => asm.FullName.StartsWith("CR_ExtUnitTest", StringComparison.InvariantCulture), - asm => asm.FullName.StartsWith("mscorlib,", StringComparison.InvariantCulture), - asm => asm.FullName.StartsWith("CR_VSTest", StringComparison.InvariantCulture), - asm => asm.FullName.StartsWith("DevExpress.CodeRush", StringComparison.InvariantCulture), - }; - - foreach (var check in ignoreChecks) - { - if (check(assembly)) - return true; - } - - return false; - } - - private bool IsIgnoredType(Type type) - { - // TODO - find a better way to remove "system" types from the auto registration - var ignoreChecks = new List>() - { - t => t.FullName.StartsWith("System.", StringComparison.InvariantCulture), - t => t.FullName.StartsWith("Microsoft.", StringComparison.InvariantCulture), - t => t.IsPrimitive, -#if !UNBOUND_GENERICS_GETCONSTRUCTORS - t => t.IsGenericTypeDefinition, -#endif - t => (t.GetConstructors(BindingFlags.Instance | BindingFlags.Public).Length == 0) && !(t.IsInterface || t.IsAbstract), - }; - - foreach (var check in ignoreChecks) - { - if (check(type)) - return true; - } - - return false; - } - - private void RegisterDefaultTypes() - { - Register(this); - -#if TINYMESSENGER - // Only register the TinyMessenger singleton if we are the root container - if (_Parent == null) - Register(); -#endif - } - - private ObjectFactoryBase GetCurrentFactory(TypeRegistration registration) - { - ObjectFactoryBase current = null; - - _RegisteredTypes.TryGetValue(registration, out current); - - return current; - } - - private RegisterOptions RegisterInternal(Type registerType, string name, ObjectFactoryBase factory) - { - var typeRegistration = new TypeRegistration(registerType, name); - - return AddUpdateRegistration(typeRegistration, factory); - } - - private RegisterOptions AddUpdateRegistration(TypeRegistration typeRegistration, ObjectFactoryBase factory) - { - _RegisteredTypes[typeRegistration] = factory; - - return new RegisterOptions(this, typeRegistration); - } - - private void RemoveRegistration(TypeRegistration typeRegistration) - { - _RegisteredTypes.Remove(typeRegistration); - } - - private ObjectFactoryBase GetDefaultObjectFactory() - where RegisterType : class - where RegisterImplementation : class, RegisterType - { - if (typeof(RegisterType).IsInterface || typeof(RegisterType).IsAbstract) - return new SingletonFactory(); - - return new MultiInstanceFactory(); - } - - private bool CanResolveInternal(TypeRegistration registration, NamedParameterOverloads parameters, ResolveOptions options) - { - if (parameters == null) - throw new ArgumentNullException("parameters"); - - Type checkType = registration.Type; - string name = registration.Name; - - ObjectFactoryBase factory; - if (_RegisteredTypes.TryGetValue(new TypeRegistration(checkType, name), out factory)) - { - if (factory.AssumeConstruction) - return true; - - if (factory.Constructor == null) - return (GetBestConstructor(factory.CreatesType, parameters, options) != null) ? true : false; - else - return CanConstruct(factory.Constructor, parameters, options); - } - - // Fail if requesting named resolution and settings set to fail if unresolved - // Or bubble up if we have a parent - if (!String.IsNullOrEmpty(name) && options.NamedResolutionFailureAction == NamedResolutionFailureActions.Fail) - return (_Parent != null) ? _Parent.CanResolveInternal(registration, parameters, options) : false; - - // Attemped unnamed fallback container resolution if relevant and requested - if (!String.IsNullOrEmpty(name) && options.NamedResolutionFailureAction == NamedResolutionFailureActions.AttemptUnnamedResolution) - { - if (_RegisteredTypes.TryGetValue(new TypeRegistration(checkType), out factory)) - { - if (factory.AssumeConstruction) - return true; - - return (GetBestConstructor(factory.CreatesType, parameters, options) != null) ? true : false; - } - } - - // Check if type is an automatic lazy factory request - if (IsAutomaticLazyFactoryRequest(checkType)) - return true; - - // Check if type is an IEnumerable - if (IsIEnumerableRequest(registration.Type)) - return true; - - // Attempt unregistered construction if possible and requested - // If we cant', bubble if we have a parent - if ((options.UnregisteredResolutionAction == UnregisteredResolutionActions.AttemptResolve) || (checkType.IsGenericType && options.UnregisteredResolutionAction == UnregisteredResolutionActions.GenericsOnly)) - return (GetBestConstructor(checkType, parameters, options) != null) ? true : (_Parent != null) ? _Parent.CanResolveInternal(registration, parameters, options) : false; - - // Bubble resolution up the container tree if we have a parent - if (_Parent != null) - return _Parent.CanResolveInternal(registration, parameters, options); - - return false; - } - - private bool IsIEnumerableRequest(Type type) - { - if (!type.IsGenericType) - return false; - - Type genericType = type.GetGenericTypeDefinition(); - - if (genericType == typeof(IEnumerable<>)) - return true; - - return false; - } - - private bool IsAutomaticLazyFactoryRequest(Type type) - { - if (!type.IsGenericType) - return false; - - Type genericType = type.GetGenericTypeDefinition(); - - // Just a func - if (genericType == typeof(Func<>)) - return true; - - // 2 parameter func with string as first parameter (name) - if ((genericType == typeof(Func<,>) && type.GetGenericArguments()[0] == typeof(string))) - return true; - - // 3 parameter func with string as first parameter (name) and IDictionary as second (parameters) - if ((genericType == typeof(Func<,,>) && type.GetGenericArguments()[0] == typeof(string) && type.GetGenericArguments()[1] == typeof(IDictionary))) - return true; - - return false; - } - - private object ResolveInternal(TypeRegistration registration, NamedParameterOverloads parameters, ResolveOptions options) - { - ObjectFactoryBase factory; - - // Attempt container resolution - if (_RegisteredTypes.TryGetValue(registration, out factory)) - { - try - { - return factory.GetObject(this, parameters, options); - } - catch (Exception ex) - { - throw new TinyIoCResolutionException(registration.Type, ex); - } - } - - // Fail if requesting named resolution and settings set to fail if unresolved - if (!String.IsNullOrEmpty(registration.Name) && options.NamedResolutionFailureAction == NamedResolutionFailureActions.Fail) - { - // Bubble resolution up the container tree if we have a parent - if (_Parent != null) - return _Parent.ResolveInternal(registration, parameters, options); - else - throw new TinyIoCResolutionException(registration.Type); - } - - // Attemped unnamed fallback container resolution if relevant and requested - if (!String.IsNullOrEmpty(registration.Name) && options.NamedResolutionFailureAction == NamedResolutionFailureActions.AttemptUnnamedResolution) - { - if (_RegisteredTypes.TryGetValue(new TypeRegistration(registration.Type, string.Empty), out factory)) - { - try - { - return factory.GetObject(this, parameters, options); - } - catch (Exception ex) - { - throw new TinyIoCResolutionException(registration.Type, ex); - } - } - } - -#if EXPRESSIONS - // Attempt to construct an automatic lazy factory if possible - if (IsAutomaticLazyFactoryRequest(registration.Type)) - return GetLazyAutomaticFactoryRequest(registration.Type); -#endif - if (IsIEnumerableRequest(registration.Type)) - return GetIEnumerableRequest(registration.Type); - - // Attempt unregistered construction if possible and requested - if ((options.UnregisteredResolutionAction == UnregisteredResolutionActions.AttemptResolve) || (registration.Type.IsGenericType && options.UnregisteredResolutionAction == UnregisteredResolutionActions.GenericsOnly)) - { - if (!registration.Type.IsAbstract && !registration.Type.IsInterface) - return ConstructType(registration.Type, parameters, options); - } - - // Bubble resolution up the container tree if we have a parent - if (_Parent != null) - return _Parent.ResolveInternal(registration, parameters, options); - - // Unable to resolve - throw - throw new TinyIoCResolutionException(registration.Type); - } - -#if EXPRESSIONS - private object GetLazyAutomaticFactoryRequest(Type type) - { - if (!type.IsGenericType) - return null; - - Type genericType = type.GetGenericTypeDefinition(); - Type[] genericArguments = type.GetGenericArguments(); - - // Just a func - if (genericType == typeof(Func<>)) - { - Type returnType = genericArguments[0]; - - MethodInfo resolveMethod = typeof(TinyIoCContainer).GetMethod("Resolve", new Type[] { }); - resolveMethod = resolveMethod.MakeGenericMethod(returnType); - - var resolveCall = Expression.Call(Expression.Constant(this), resolveMethod); - - var resolveLambda = Expression.Lambda(resolveCall).Compile(); - - return resolveLambda; - } - - // 2 parameter func with string as first parameter (name) - if ((genericType == typeof(Func<,>)) && (genericArguments[0] == typeof(string))) - { - Type returnType = genericArguments[1]; - - MethodInfo resolveMethod = typeof(TinyIoCContainer).GetMethod("Resolve", new Type[] { typeof(String) }); - resolveMethod = resolveMethod.MakeGenericMethod(returnType); - - ParameterExpression[] resolveParameters = new ParameterExpression[] { Expression.Parameter(typeof(String), "name") }; - var resolveCall = Expression.Call(Expression.Constant(this), resolveMethod, resolveParameters); - - var resolveLambda = Expression.Lambda(resolveCall, resolveParameters).Compile(); - - return resolveLambda; - } - - // 3 parameter func with string as first parameter (name) and IDictionary as second (parameters) - if ((genericType == typeof(Func<,,>) && type.GetGenericArguments()[0] == typeof(string) && type.GetGenericArguments()[1] == typeof(IDictionary))) - { - Type returnType = genericArguments[2]; - - var name = Expression.Parameter(typeof(string), "name"); - var parameters = Expression.Parameter(typeof(IDictionary), "parameters"); - - MethodInfo resolveMethod = typeof(TinyIoCContainer).GetMethod("Resolve", new Type[] { typeof(String), typeof(NamedParameterOverloads) }); - resolveMethod = resolveMethod.MakeGenericMethod(returnType); - - var resolveCall = Expression.Call(Expression.Constant(this), resolveMethod, name, Expression.Call(typeof(NamedParameterOverloads), "FromIDictionary", null, parameters)); - - var resolveLambda = Expression.Lambda(resolveCall, name, parameters).Compile(); - - return resolveLambda; - } - - throw new TinyIoCResolutionException(type); - } -#endif - private object GetIEnumerableRequest(Type type) - { - // Using MakeGenericMethod (slow) because we need to - // cast the IEnumerable or constructing the type wil fail. - // We may as well use the ResolveAll public - // method to do this. - var resolveAllMethod = this.GetType().GetMethod("ResolveAll", new Type[] { }); - var genericResolveAllMethod = resolveAllMethod.MakeGenericMethod(type.GetGenericArguments()[0]); - return genericResolveAllMethod.Invoke(this, new object[] { }); - } - - private bool CanConstruct(ConstructorInfo ctor, NamedParameterOverloads parameters, ResolveOptions options) - { - if (parameters == null) - throw new ArgumentNullException("parameters"); - - foreach (var parameter in ctor.GetParameters()) - { - if (string.IsNullOrEmpty(parameter.Name)) - return false; - - var isParameterOverload = parameters.ContainsKey(parameter.Name); - - if (parameter.ParameterType.IsPrimitive && !isParameterOverload) - return false; - - if (!isParameterOverload && !CanResolveInternal(new TypeRegistration(parameter.ParameterType), NamedParameterOverloads.Default, options)) - return false; - } - - return true; - } - - private ConstructorInfo GetBestConstructor(Type type, NamedParameterOverloads parameters, ResolveOptions options) - { - if (parameters == null) - throw new ArgumentNullException("parameters"); - - if (type.IsValueType) - return null; - - // Get constructors in reverse order based on the number of parameters - // i.e. be as "greedy" as possible so we satify the most amount of dependencies possible - var ctors = from ctor in type.GetConstructors() - orderby ctor.GetParameters().Count() descending - select ctor; - - foreach (var ctor in ctors) - { - if (CanConstruct(ctor, parameters, options)) - return ctor; - } - - return null; - } - - private object ConstructType(Type type, ResolveOptions options) - { - return ConstructType(type, null, NamedParameterOverloads.Default, options); - } - - private object ConstructType(Type type, ConstructorInfo constructor, ResolveOptions options) - { - return ConstructType(type, constructor, NamedParameterOverloads.Default, options); - } - - private object ConstructType(Type type, NamedParameterOverloads parameters, ResolveOptions options) - { - return ConstructType(type, null, parameters, options); - } - - private object ConstructType(Type type, ConstructorInfo constructor, NamedParameterOverloads parameters, ResolveOptions options) - { - if (constructor == null) - constructor = GetBestConstructor(type, parameters, options); - - if (constructor == null) - throw new TinyIoCResolutionException(type); - - var ctorParams = constructor.GetParameters(); - object[] args = new object[ctorParams.Count()]; - - for (int parameterIndex = 0; parameterIndex < ctorParams.Count(); parameterIndex++) - { - var currentParam = ctorParams[parameterIndex]; - - args[parameterIndex] = parameters.ContainsKey(currentParam.Name) ? parameters[currentParam.Name] : ResolveInternal(new TypeRegistration(currentParam.ParameterType), NamedParameterOverloads.Default, options); - } - - try - { - return constructor.Invoke(args); - } - catch (Exception ex) - { - throw new TinyIoCResolutionException(type, ex); - } - } - - private void BuildUpInternal(object input, ResolveOptions resolveOptions) - { - var properties = from property in input.GetType().GetProperties() - where (property.GetGetMethod() != null) && (property.GetSetMethod() != null) && !property.PropertyType.IsValueType - select property; - - foreach (var property in properties) - { - if (property.GetValue(input, null) == null) - { - try - { - property.SetValue(input, ResolveInternal(new TypeRegistration(property.PropertyType), NamedParameterOverloads.Default, resolveOptions), null); - } - catch (TinyIoCResolutionException) - { - // Catch any resolution errors and ignore them - } - } - } - } - - private IEnumerable ResolveAllInternal(Type resolveType, bool includeUnnamed) - { - var registrations = _RegisteredTypes.Keys.Where(tr => tr.Type == resolveType); - - if (!includeUnnamed) - registrations = registrations.Where(tr => tr.Name != string.Empty); - - foreach (var registration in registrations) - { - yield return ResolveInternal(registration, NamedParameterOverloads.Default, ResolveOptions.Default); - } - } - - private RegisterOptions ExecuteGenericRegister(Type[] genericParameterTypes, Type[] methodParameterTypes, object[] methodParameters) - { - try - { - var method = this.GetType().GetGenericMethod(BindingFlags.Instance | BindingFlags.Public, "Register", genericParameterTypes, methodParameterTypes); - - return (RegisterOptions)method.Invoke(this, methodParameters); - } - catch (ArgumentException ex) - { - var registrationType = genericParameterTypes[0]; - var implementationType = genericParameterTypes[1]; - - if (genericParameterTypes.Length == 2) - implementationType = genericParameterTypes[2]; - - throw new TinyIoCRegistrationException(registrationType, implementationType, ex); - } - } - #endregion - - #region IDisposable Members - bool disposed = false; - public void Dispose() - { - if (!disposed) - { - disposed = true; - - _RegisteredTypes.Dispose(); - - GC.SuppressFinalize(this); - } - } - - #endregion - } -} diff --git a/MonoStockPortfolio/MonoStockPortfolio.csproj b/MonoStockPortfolio/MonoStockPortfolio.csproj index 5ac7680..1003a97 100644 --- a/MonoStockPortfolio/MonoStockPortfolio.csproj +++ b/MonoStockPortfolio/MonoStockPortfolio.csproj @@ -69,6 +69,7 @@ PortfolioActivity.cs + diff --git a/libs/xunit.dll b/libs/xunit.dll new file mode 100644 index 0000000000000000000000000000000000000000..423fbbcf07e4d85055e54a9ec418fa0706f543b3 GIT binary patch literal 61952 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 z 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 Date: Sat, 5 Feb 2011 20:40:52 -0500 Subject: [PATCH 6/6] removed TinyIoC from csproj --- MonoStockPortfolio/MonoStockPortfolio.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/MonoStockPortfolio/MonoStockPortfolio.csproj b/MonoStockPortfolio/MonoStockPortfolio.csproj index 1003a97..0b4ebe2 100644 --- a/MonoStockPortfolio/MonoStockPortfolio.csproj +++ b/MonoStockPortfolio/MonoStockPortfolio.csproj @@ -71,7 +71,6 @@ -