I am currently using iBATIS.NET for a small application I am building. I like to create concrete Classes for my DAOs instead of using ISqlMapper directly and invoking named SQL statements. I am not using a Dependency Injection container of any sort, so ideally I have my DAOs set up as follows:
public abstract class AbstractDAO
{
/// <summary>
/// SQL Mapper.
/// </summary>
ISqlMapper mapper;
/// <summary>
/// Default Constructor.
/// </summary>
/// <param name="mapper"></param>
public AbstractDAO(ISqlMapper mapper)
{
this.mapper = mapper;
}
}
public class NodeDAO : AbstractDAO
{
/// <summary>
/// Default Constructor.
/// </summary>
/// <param name="mapper"></param>
public NodeDAO(ISqlMapper mapper) : base(mapper) { }
/// <summary>
/// Insert Node.
/// </summary>
/// <param name="node"></param>
public void InsertNode(Node node)
{
// ... Assume Some Pretty Code.
}
}
public class NodeRevisionDAO : AbstractDAO
{
/// <summary>
/// Default Constructor.
/// </summary>
/// <param name="mapper"></param>
public NodeRevisionDAO (ISqlMapper mapper) : base(mapper) { }
/// <summary>
/// Insert Node Revision.
/// </summary>
/// <param name="nodeRevision"></param>
public void InsertNodeRevision(NodeRevision nodeRevision)
{
// ... Assume Some Pretty Code.
}
}
From my main application code, let's say in some form of Business Layer, I would ideally call two insert Methods on the DAOs:
// ... Assume DAOs are Initialized.
nodeDAO.InsertNode(node);
nodeRevisionDAO.InsertNodeRevision(nodeRevision);
I want to make sure both statements are executed as an atomic operation in a transaction so that if either fails, both will be rolled back. But because the ISqlMapper is injected in both DAOs I have no control over the transactions.
What would be the best approach to this problem? Putting it in another way, how can I handle transactions without exposing the ISqlMapper?
Related
How do we generate the ITokenBuilder class/interface in C# that has all the necessary tags and stuff like in the code snippet below:
/// <summary>
/// Initializes a new instance of the <see cref="Token"/> class.
/// </summary>
/// <param name="builder">Token builder</param>
protected Token(ITokenBuilder builder)
{
Lexeme = builder.Lexeme;
LeftTrivia = builder.LeftTrivia;
RightTrivia = builder.RightTrivia;
}
Do I need to manually type in the /// <summary> stuff?
I have the following logger logger class and I want to know the best to unit testing it.
Some observations:
I needed to create the interface IFileWrapper in order to break dependency with System.IO dependency and been able to user dependency injection (Autofac)
I was able to unit testing the method FileWrapper.WriteLog by implementing IFileWrapper using a MemoryString but if I wanted to test a expected behavior inside the method I won't be able (e.g: throwing exceptions, incorrect path and filename, etc.)
/// <summary>
/// Creates an instance of type <see cref="FileLogger"/>
/// </summary>
/// <remarks>Implements the Singleton Pattern</remarks>
private FileLogger()
{
FileName = string.Format("\\{0: MMM dd, yy}.log", DateTime.Now);
Path = Environment.CurrentDirectory;
FileWrapper = ContainerBuilderFactory.Container.Resolve<IFileWrapper>();
}
/// <summary>
/// Log the <paramref name="Message"/> in the <paramref name="Path"/> specified.
/// The <paramref name="UserName"/>, <paramref name="Host"/> must be supplied
/// </summary>
/// <example>
/// <code>
/// var handler = new LoggerHandlerFactory();
/// var logger = handler.GetHandler<FileLogger>();
/// logger.Log("Hello CSharpLogger");
/// </code>
/// </example>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="NotSupportedException"></exception>
/// <exception cref="FileNotFoundException"></exception>
/// <exception cref="IOException"></exception>
/// <exception cref="SecurityException"></exception>
/// <exception cref="DirectoryNotFoundException"></exception>
/// <exception cref="UnauthorizedAccessException"></exception>
/// <exception cref="PathTooLongException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="FormatException"></exception>
public void Log(string message, LogLevel level = LogLevel.INFO)
{
lock (_current)
{
var configLevel = CSharpLoggerConfiguration.Configuration.GetLogLevel();
if (configLevel != LogLevel.OFF & level != LogLevel.OFF && configLevel >= level)
{
try
{
FileWrapper.WriteLog(string.Concat(Path, FileName), message, level);
}
catch (CSharpLoggerException)
{
throw;
}
}
}
}
So, I created the following UnitTesting using Moq:
//arrange
CSharpLoggerConfiguration.Configuration.SetLogLevel(LogLevel.DEBUG);
var mock = new Mock<IFileWrapper>();
mock.Setup(x => x.WriteLog(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<LogLevel>()));
logger.FileWrapper = mock.Object;
//act
logger.Log("Hello CSharpLogger", LogLevel.DEBUG);
logger.Log("Hello CSharpLogger", LogLevel.WARN);
//assert
mock.Verify(x => x.WriteLog(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<LogLevel>()), Times.Exactly(2));
So far so good. What I'm not confortable is with this line: logger.FileWrapper = mock.Object; I would like to keep FileWrapper propety private.
Any advise is welcome.
I'll be publishing the code http://csharplogger.codeplex.com/ in case you want more details.
Use constructor injection. In short; instead of providing the service (in this case the file wrapper) by setting a property, make the logger have a public constructor which takes an IFileWrapper argument.
public class Logger
{
public Logger(IFileWrapper fileWrapper)
{
FileWrapper = fileWrapper;
}
public IFileWrapper FileWrapper { get; }
}
// in your test:
var logger = new Logger(mock.Object);
To answer the question about having a singleton file wrapper more thoroughly, here's a code sample for the application (non-test) code:
public static class FileWrapperFactory
{
private static IFileWrapper _fileWrapper;
public static IFileWrapper GetInstance()
{
return _fileWrapper ?? (_fileWrapper = CreateInstance());
}
private static IFileWrapper CreateInstance()
{
// do all the necessary setup here
return new FileWrapper();
}
}
public class StuffDoer
{
public void DoStuff()
{
var logger = new FileLogger(FileWrapperFactory.GetInstance());
logger.WriteLog("Starting to do stuff...");
// do stuff
logger.WriteLog("Stuff was done.");
}
}
Since the FileWrapperFactory maintains a static instance of the file wrapper, you'll never have more than one. However, you can create multiple loggers like that, and they don't have to care. If you, in the future, decide that it's OK to have many file wrappers, the logger code doesn't have to change.
In a real-world application, I'd advice you to choose some kind of DI framework to handle all this book-keeping for you; most have excellent support for singleton instances, doing essentially what the FileWrapperFactory above does (but usually in a more sophisticated and robust way. FileWrapperFactory isnt' thread-safe, for example...).
Since your code comments show that your logger is a singleton, you need a way other than constructor injection for setting the dependency. In his book on Legacy Code, Mike Feathers suggests a function for such purposes, which is adequately named, something like
public void SetInstanceForTesting(IFileWrapper fileWrapper) {...}
Now this function won't hopefully be used for different purposes...
Problem
My application use accelerometer data via Microsoft.Devices.Sensors.Accelerometer class
Now I wanna write Unit or CodedUI tests, for this reason I need to have a special test implementation of Accelerometer to controlling returned data
In theory I have 3 options:
Create subclass of Accelerometer - impossible because Accelerometer is sealed class
By using reflection replace implementation of Accelerometer at run-time - isn't best option IMHO
Create subclass of SensorBase<AccelerometerReading> - good option
I have decided to go by #1 and implement my TestAccelerometer as child of SensorBase<AccelerometerReading>
And here is I have problem:
`Error CS1729 'SensorBase<AccelerometerReading>' does not contain a constructor that takes 0 arguments`
Error pretty clear I have looked in decompiled code (JetBrains dotPeak tool) and don't found any constructors at all.
Questions
How can I found proper constructor to use in my TestAccelerometer implementation?
Decompiled code
Microsoft.Devices.Sensors.Accelerometer
// Type: Microsoft.Devices.Sensors.Accelerometer
// Assembly: Microsoft.Devices.Sensors, Version=8.0.0.0, Culture=neutral, PublicKeyToken=24eec0d8c86cda1e
// MVID: 81ED89AA-6B11-4B39-BAFA-38D59CBB1E3B
// Assembly location: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\WindowsPhone\v8.0\Microsoft.Devices.Sensors.dll
using System;
namespace Microsoft.Devices.Sensors
{
/// <summary>
/// Provides Windows Phone applications access to the device’s accelerometer sensor.
/// </summary>
public sealed class Accelerometer : SensorBase<AccelerometerReading>
{
/// <summary>
/// Gets or sets whether the device on which the application is running supports the accelerometer sensor.
/// </summary>
///
/// <returns>
/// true if the device on which the application is running supports the accelerometer sensor; otherwise, false.
/// </returns>
public static bool IsSupported { get; internal set; }
/// <summary>
/// Gets the current state of the accelerometer. The value is a member of the <see cref="T:Microsoft.Devices.Sensors.SensorState"/> enumeration.
/// </summary>
///
/// <returns>
/// Type: <see cref="T:Microsoft.Devices.Sensors.SensorState"/>.
/// </returns>
public SensorState State { get; private set; }
/// <summary>
/// Occurs when new data arrives from the accelerometer. This method is deprecated in the current release. Applications should use the <see cref="E:Microsoft.Devices.Sensors.SensorBase`1.CurrentValueChanged"/> event of the <see cref="T:Microsoft.Devices.Sensors.SensorBase`1"/> class instead.
/// </summary>
[Obsolete("use CurrentValueChanged")]
public event EventHandler<AccelerometerReadingEventArgs> ReadingChanged;
static Accelerometer();
/// <summary>
/// Releases the managed and unmanaged resources used by the <see cref="T:Microsoft.Devices.Sensors.Accelerometer"/>.
/// </summary>
public new void Dispose();
/// <summary>
/// Starts data acquisition from the accelerometer.
/// </summary>
public new void Start();
/// <summary>
/// Stops data acquisition from the accelerometer.
/// </summary>
public new void Stop();
}
}
Microsoft.Devices.Sensors.SensorBase
// Type: Microsoft.Devices.Sensors.SensorBase`1
// Assembly: Microsoft.Devices.Sensors, Version=8.0.0.0, Culture=neutral, PublicKeyToken=24eec0d8c86cda1e
// MVID: 81ED89AA-6B11-4B39-BAFA-38D59CBB1E3B
// Assembly location: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\WindowsPhone\v8.0\Microsoft.Devices.Sensors.dll
using System;
using System.Security;
namespace Microsoft.Devices.Sensors
{
/// <summary>
/// The base class for all Windows Phone sensor classes.
/// </summary>
/// <typeparam name="TSensorReading">The type of reading returned by the sensor.</typeparam>
public abstract class SensorBase<TSensorReading> : IDisposable where TSensorReading : ISensorReading
{
/// <summary>
/// Gets an object that implements <see cref="T:Microsoft.Devices.Sensors.ISensorReading"/> that contains the current value of the sensor. This object will be one of the following types, depending on which sensor is being referenced: <see cref="T:Microsoft.Devices.Sensors.AccelerometerReading"/>, <see cref="T:Microsoft.Devices.Sensors.CompassReading"/>, <see cref="T:Microsoft.Devices.Sensors.GyroscopeReading"/>, <see cref="T:Microsoft.Devices.Sensors.MotionReading"/>.
/// </summary>
///
/// <returns>
/// An object that implements <see cref="T:Microsoft.Devices.Sensors.ISensorReading"/> that contains the current value of the sensor.
/// </returns>
public TSensorReading CurrentValue { get; }
/// <summary>
/// Gets or sets the preferred time between <see cref="E:Microsoft.Devices.Sensors.SensorBase`1.CurrentValueChanged"/> events.
/// </summary>
///
/// <returns>
/// Type: <see cref="T:System.TimeSpan"/>. The preferred time between CurrentValueChanged events.
/// </returns>
public TimeSpan TimeBetweenUpdates { get; set; }
/// <summary>
/// Gets the validity of the sensor’s data.
/// </summary>
///
/// <returns>
/// Type: <see cref="T:System.Boolean"/>. true if the sensor’s data is valid; otherwise, false.
/// </returns>
public bool IsDataValid { get; }
/// <summary>
/// Occurs when new data arrives from the sensor.
/// </summary>
public event EventHandler<SensorReadingEventArgs<TSensorReading>> CurrentValueChanged;
static SensorBase();
internal SensorBase();
/// <summary>
/// Allows an object to try to free resources and perform other cleanup operations before the Object is reclaimed by garbage collection.
/// </summary>
[SecuritySafeCritical]
~SensorBase();
/// <summary>
/// Releases the managed and unmanaged resources used by the sensor.
/// </summary>
[SecuritySafeCritical]
public void Dispose();
/// <summary>
/// Starts acquisition of data from the sensor.
/// </summary>
public virtual void Start();
/// <summary>
/// Stops acquisition of data from the sensor.
/// </summary>
public virtual void Stop();
}
}
You did find a constructor:
internal SensorBase();
This constructor prevents the SensorBase from having a default public constructor and this class cannot be subclassed from outside its assembly.
Testing it will be complicated. You could redesign the app and use a wrapper/adapter for the Accelerometer just for the puropse of testing or you could check if there's a possibility of mocking a sealed class on Windows Phone.
I have an operation contract in my service contract called
Schedule[] GetScheduleObjects();
I have a datameber in that operation contract called "Tasks" that returns a list of sub objects.
[DataMember()]
public Task[] Tasks
The issues is when the operation contract is called the method executes but the "get" of "Tasks" occurs twice. The first time it contains valid runtime instances, the second time it is null which causes a serialization exception. This happens despite only one call to the service. The binding is a tcp connection using a duplex proxy. Ideas?????
The Datacontract
[DataContract()]
public class Schedule
{
public Schedule(string name)
{
this.Name = name;
}
[DataMember()]
public string Name { get; private set; }
[DataMember()]
public bool Running { get; set; }
/// <summary>
/// Schedule Task is a DataMember object, do not modify
/// </summary>
[DataMember()]
public Task[] Tasks
{
get { return _Tasks.ToArray(); }
}
private List<Task> _Tasks = new List<Task>();
///<summary>
/// Use this property to add objects
///</summary>
public List<Task> ScheduleTasks
{
get { return _Tasks; }
}
}
The service contract
[ServiceContract(CallbackContract = typeof(ISummitDashboardCallbackContract))]
public interface ISchedulerContract : ISummitDashboardContract
{
/// <summary>
/// Sets the named schedule into "run" mode
/// </summary>
/// <param name="scheduleName"></param>
/// <returns></returns>
[OperationContract()]
void StartSchedule(string scheduleName);
/// <summary>
/// Pauses the currently running schedule
/// </summary>
/// <param name="scheduleName"></param>
[OperationContract()]
void PauseSchedule(string scheduleName);
/// <summary>
/// Removes the named schedule from "run" mode
/// </summary>
/// <param name="scheduleName"></param>
/// <returns></returns>
[OperationContract()]
void StopSchedule(string scheduleName);
/// <summary>
/// Flips the "active" state of the task with the named id
/// </summary>
/// <param name="scheduleName"></param>
/// <param name="Id"></param>
[OperationContract()]
void ToggleTaskState(string scheduleName, string Id);
/// <summary>
/// Flips the "active" state of the action with the named id
/// </summary>
/// <param name="scheduleName"></param>
/// <param name="Id"></param>
/// <returns></returns>
[OperationContract()]
void ToggleActionState(string scheduleName, string Id);
/// <summary>
/// Returns the information to build the tree list in the dashboard
/// </summary>
/// <returns></returns>
[OperationContract()]
Schedule[] GetScheduleObjects();
/// <summary>
/// Returns the events of the scheduler
/// </summary>
/// <returns></returns>
[OperationContract()]
SchedulerEvent[] GetSchedulerEvents(int startIndex, int count, int eventLogEntryType);
}
You'll need to add a setter to property Tasks, and you'll also need to increase the visibility of Name to at least protected - WCF will need to use these in order to deserialize objects of this class.
As a secondary issue, if a client generates a proxy (e.g. with Add Service Reference or via SvcUtil.exe), the 'code behind' Tasks (i.e. return _Tasks.ToArray(); which is coupled to ScheduledTasks) will be lost, and the client will instead just get a simple automatic backing property to property Tasks (with the collection class selected during the proxy generation). This second issue won't however happen however if you share type.
Not sure if I'm even calling this right but I wanted to start adding some documentation to my classes, methods, properties, etc. I know this is probably super obvious but I never really learned it. I'm not sure where to start.
Just to clarify whenever you roll over a class (or method, property, etc.) it shows a tooltip in Visual Studio with some documentation on that specific method.
class Microsoft.Phone.BackgroundAudio.BackgroundAudioPlayer
Provides background access to audio playback functionality such as play, pause, fast-forward, and rewind.
What is that called and how can I implement this in my C# application?
You can use /// or GhostDoc
Edit:
In first case you'll get
/// <summary>
///
/// </summary>
class A
{
/// <summary>
///
/// </summary>
public A() { }
/// <summary>
///
/// </summary>
public int Property { get; set; }
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
public void Method(object obj) { }
}
In second
/// <summary>
///
/// </summary>
class B
{
/// <summary>
/// Initializes a new instance of the <see cref="B"/> class.
/// </summary>
public B() { }
/// <summary>
/// Gets or sets the property.
/// </summary>
/// <value>
/// The property.
/// </value>
public int Property { get; set; }
/// <summary>
/// Methods the specified obj.
/// </summary>
/// <param name="obj">The obj.</param>
public void Method(object obj) { }
}
Just above your class, method or property, type /// then press return. This will generate the documentation template for you.
Forgot to answer the other part of your question: this is known as XML Documentation Comments and there is a substantial amount of information about this in MSDN.
What you are referring to is called XML documentation or XML-doc.
XML-doc is performed on a class, field, property, event or method using three forward-slashes (///), followed by XML-formatted meta-information about the class or its member.
VS will help you generate and format these comments with built-in IntelliSense support for XML comments, but there is a free tool called GhostDoc that will automatically generate the full XML-doc template, and it's even "smart" enough in some cases to try to guess a basic description for various elements of the documentation.
Here's a basic example of XML documentation:
/// <summary>
/// Defines the behavior of a class following the Repository pattern for data access
/// with basic atomic operation control.
/// </summary>
/// <typeparam name="TRest">An interface derived from IDomainObject that describes domain objects
/// that can be retrieved or saved by this Repository.</typeparam>
public interface IRepository<TRest> : IDisposable where TRest : IDomainObject
{
/// <summary>
/// Begins a new unit of work to be performed atomically by the Repository.
/// </summary>
/// <returns>A token class representing the unit of work.</returns>
IUnitOfWork BeginUnitOfWork();
/// <summary>
/// Commits all work performed under the specified unit of work.
/// </summary>
/// <param name="unitOfWork">The unit of work.</param>
void CommitUnitOfWork(IUnitOfWork unitOfWork);
/// <summary>
/// Rolls back the specified unit of work.
/// </summary>
/// <param name="unitOfWork">The unit of work.</param>
void RollBackUnitOfWork(IUnitOfWork unitOfWork);
/// <summary>
/// Saves the specified domain object to the data source controlled by the repository.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="domainObject">The domain object.</param>
/// <param name="unitOfWork">The unit of work.</param>
void Save<T>(T domainObject, IUnitOfWork unitOfWork) where T : class, TRest;
/// <summary>
/// Begins a Linq query for a specific object type, to be performed against the Repository's data source.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="unitOfWork">The unit of work.</param>
/// <returns>An IQueryable representing the query to be performed.</returns>
IQueryable<T> QueryFor<T>(IUnitOfWork unitOfWork) where T : class, TRest;
/// <summary>
/// Performs the specified Action using a new unit of work, with commits and rollbacks as necessary.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func">The Action to perform. The lambda or named method must accept an IUnitOfWork as a parameter.</param>
/// <param name="commit">if set to <c>true</c>, commit the unit of work.</param>
void PerformInNewUnitOfWork<T>(Action<IUnitOfWork> func, bool commit = false);
/// <summary>
/// Performs the specified Func using a new unit of work, with commits and rollbacks as necessary.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func">The function to evaluate. The lambda or named method must accept an IUnitOfWork as a parameter.</param>
/// <returns>A single object of the generic type, returned by the function.</returns>
/// <param name="commit">if set to <c>true</c>, commit the unit of work.</param>
T PerformInNewUnitOfWork<T>(Func<IUnitOfWork, T> func, bool commit = false) where T : class, TRest;
/// <summary>
/// Performs the specified Func using a new unit of work, with commits and rollbacks as necessary.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func">The Function to evaluate. The lambda or named method must accept an IUnitOfWork as a parameter.</param>
/// <returns>An enumerable set of objects of the generic type, returned by the function.</returns>
/// <param name="commit">if set to <c>true</c>, commit the unit of work.</param>
IEnumerable<T> PerformInNewUnitOfWork<T>(Func<IUnitOfWork, IEnumerable<T>> func, bool commit = false) where T : class, TRest;
/// <summary>
/// Attaches the specified domain object to the current Unit of Work, allowing operations to be performed on it.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="domainObject">The domain object.</param>
/// <param name="unitOfWork">The unit of work.</param>
void Attach<T>(T domainObject, IUnitOfWork unitOfWork) where T : class, TRest;
/// <summary>
/// Detaches the specified domain object to the current Unit of Work.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="domainObject">The domain object.</param>
/// <param name="unitOfWork">The unit of work.</param>
void Detach<T>(T domainObject, IUnitOfWork unitOfWork) where T : class, TRest;
/// <summary>
/// Refreshes the specified collection of persistent elements with the most recent persisted data.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="elements">The list of elements to refresh.</param>
/// <param name="unitOfWork">The Unit of Work under which to perform the operation.</param>
void Refresh<T>(IList<T> elements, IUnitOfWork unitOfWork) where T : class, TRest;
/// <summary>
/// Deletes the specified domain object from the data store.
/// Usually performs a physical delete; logical deletes are most often done through updates.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="domainObject">The domain object to delete.</param>
/// <param name="unitOfWork">The unit of work under which to perform the operation.</param>
void Delete<T>(T domainObject, IUnitOfWork unitOfWork) where T : class, TRest;
}