I'm trying to convert this c# code into c++/cli code:
class MyRange : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator() { return null; }
IEnumerator IEnumerable.GetEnumerator() { return null; }
}
Here is my attempt:
namespace Tests {
public ref class MyRange : System::Collections::Generic::IEnumerable<int> {
private:
virtual System::Collections::IEnumerator^ GetEnumerator() = System::Collections::IEnumerable::GetEnumerator {
return nullptr;
}
virtual System::Collections::Generic::IEnumerable<int>^ GetEnumerator() {
return nullptr;
}
};
}
It's giving me so many errors (like 20), that I don't even think it's worth putting them here.
I've googled it all and it seems like a lot of people are having the same problem as me.
Ok, after a lot of fighting found some working code:
namespace Tests {
ref class MyCollection : public Generic::IEnumerable<int>
{
public:
virtual System::Collections::IEnumerator^ GetEnumeratorNonGeneric() = System::Collections::IEnumerable::GetEnumerator
{
return GetEnumerator();
}
virtual Generic::IEnumerator<int>^ MyCollection::GetEnumerator()
{
return nullptr;
}
};
}
It's often helpful to disassemble your C# in Reflector using Managed C++ as the target language and then from there do the translation to C++/CLI.
Related
I've two projects (class library projects) which implement one interface:
The first one:
public class MailPlugin : Extensibility.IProductorPlugin
{
...
}
The second one:
public class FileSystemPlugin : Extensibility.IProductorPlugin
{
...
}
Extensibility.IProductorPlugin, is a interface of a third project:
namespace Extensibility
{
public delegate void NotifyDigitalInputs(List<Domain.DigitalInput> digital_inputs);
public interface IProductorPlugin
{
String Name { get; }
String Description { get; }
String Version { get; }
List<Domain.Channel> AvailableChannels { get; }
IEnumerable<Guid> TypeGuids { get; }
event NotifyDigitalInputs OnDigitalInputs;
}
}
In my composition root, I've created this class:
namespace UI
{
public sealed class NinjectServiceLocator
{
private static readonly Lazy<NinjectServiceLocator> lazy = new Lazy<NinjectServiceLocator>(() => new NinjectServiceLocator());
public static NinjectServiceLocator Instance { get { return lazy.Value; } }
public Ninject.IKernel Kernel { get; private set; }
private NinjectServiceLocator()
{
using (var k = this.Kernel = new Ninject.StandardKernel())
{
k.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(Extensibility.IProductorPlugin))
.BindAllInterfaces()
);
}
}
}
}
So, when I want to look for all plugins, I just perform this:
protected void initialize()
{
foreach (Extensibility.IProductorPlugin productor_plugin in NinjectServiceLocator.Instance.Kernel.GetAll(typeof(Extensibility.IProductorPlugin)))
{
using (var channel_tile = new DevExpress.XtraBars.Docking2010.Views.WindowsUI.Tile() { Group = "Plugin Channels" })
{
foreach (Domain.Channel channel in productor_plugin.AvailableChannels)
{
channel_tile.Elements.Add(new DevExpress.XtraEditors.TileItemElement() { Text = channel.Name });
channel_tile.Elements.Add(new DevExpress.XtraEditors.TileItemElement() { Text = channel.Description });
this.tileContainer1.Items.Add(channel_tile);
}
}
}
}
However, GetAll returns anything.
What am I doing wrong?
I'll appreciate a lot your help.
Thanks for all.
try removing the using() from around the Kernel instantiation. a using will dispose the object at the end of the scope, which we don't want for a kernel.
using (var k = this.Kernel = new Ninject.StandardKernel())
I'm trying to read a decimal (38,16) from a SQL Server DB and struggling. After much reading around I'm trying to implement a custom type for SQL Decimal with the following code:
public class BigDecimal : IUserType
{
public bool Equals(object x, object y)
{
return object.Equals(x,y);
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
int index = rs.GetOrdinal(names[0]);
object result = rs.GetValue(index);
return result;
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
//Not got here yet
}
public object DeepCopy(object value)
{
return value;
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return cached;
}
public object Disassemble(object value)
{
return value;
}
public SqlType[] SqlTypes { get { return new[] {SqlTypeFactory.Decimal}; } }
public Type ReturnedType { get { return typeof (SqlDecimal); } }
public bool IsMutable { get { return false; } }
}
but the output of rs.GetValue is a decimal not at SQLDecimal which causes an OverflowException.
The class looks like this:
public class Billy
{
public BigDecimal TheNumber {get;set;}
}
and the mapping looks like this:
public class BillyMap : ClassMap<Billy>
{
public BillyMap()
{
Map(b=>b.TheNumber).CustomType<BigDecimal>();
}
}
Please can someone tell me where I'm going wrong.
I think you need to cast the reader to SqlDataReader so you can access either GetSqlDecimal() or GetSqlValue(), as GetValue() will convert to a basic .Net Framework type. From 'https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getsqlvalue%28v=vs.110%29.aspx':
GetSqlValue returns data using the native SQL Server types. To retrieve data using the .NET Framework types, see GetValue.
In the end I made a something which performs a convert in the SQL and made it a Property Part and just use it on all the mapping files:
private const string DECIMAL_CONVERSION = "(CONVERT(decimal(28,6), [{0}]))";
private static string MapDecimalProperty(string fieldName)
{
return string.Format(DECIMAL_CONVERSION, fieldName.Trim('[',']'));
}
public static PropertyPart LongDecimal(this PropertyPart part, string fieldName)
{
return part.Formula(MapDecimalProperty(fieldName));
}
the on the mapping:
Map(ep => ep.BigDecimalField).EDWDecimal("[BigDecimalField]");
this works for now. I've informed the data architecture team that this is happening and they don't think that it will be a problem with any current data and will consider it for future developments.
In TypeMock you can create a future mock object, for example:
public class ClassToTest
{
public ClassToTest()
{
var o = new Foo();
}
}
[Test]
public void Test()
{
var fakeFoo = Isolate.Fake.Instance<Foo>();
Isolate.Swap.NextInstance<Foo>().With(fakeFoo);
}
Does MS Fakes have the same functionality as the above?
I found a great example from this SO question which demonstrates how to fake future instances of objects. Here's an example from that question:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
ClassLibrary1.Child myChild = new ClassLibrary1.Child();
using (ShimsContext.Create())
{
ClassLibrary1.Fakes.ShimChild.AllInstances.addressGet = (instance) => "foo";
ClassLibrary1.Fakes.ShimParent.AllInstances.NameGet = (instance) => "bar";
Assert.AreEqual("foo", myChild.address);
Assert.AreEqual("bar", myChild.Name);
}
}
}
This looks like it will do the trick for me.
I need to call a c++ callback function from c# that returns a String. When I try with the code below the application crashes hard (with a message saying that it may be due to a corruption of the heap).
Here's the c++ code:
static String^ CppFunctionThatReturnsString()
{
return gcnew String("From C++");
}
void main()
{
CSharp::CSharpFunction(IntPtr(CppFunctionThatReturnsString));
}
And here's the c# code:
public class CSharp
{
private delegate string CppFuncDelegate();
public static void CSharpFunction(IntPtr cppFunc)
{
var func = (CppFuncDelegate)Marshal.GetDelegateForFunctionPointer(cppFunc, typeof(CppFuncDelegate));
func(); // Crash
}
}
Do I have to do some kind of marshaling magic with the string before returning it?
Why are you using function pointers in the first place? Just pass an instance of the delegate to the C# code:
C++:
static String^ CppFunctionThatReturnsString()
{
return gcnew String("From C++");
}
void main()
{
CSharp::CSharpFunction(new CSharp::CppFuncDelegate(CppFuncThatReturnsString));
}
C#:
public class CSharp
{
private delegate string CppFuncDelegate();
public static void CSharpFunction(CppFuncDelegate d)
{
d();
}
}
I think you may need to put CppFuncThatReturnsString inside a class.
I found the answer on this ten year old page.
c++:
static const char* __stdcall CppFunctionThatReturnsString()
{
return "From C++";
}
void main()
{
CSharp::CSharpFunction(IntPtr(CppFunctionThatReturnsString));
}
c#:
public class CSharp
{
private delegate IntPtr CppFuncDelegate();
public static void CSharpFunction(IntPtr cppFunc)
{
var func = (CppFuncDelegate)Marshal.GetDelegateForFunctionPointer(cppFunc, typeof(CppFuncDelegate));
Marshal.PtrToStringAnsi(func());
}
}
That is, pass it as an IntPtr and marshal it into a string on the C# side.
My question is, how to redesign abstract factory.
For example, I get next abstraction of vehicles:
interface IEngine { int Power(); }
class Gasoline : IEngine { public int Power() {return 150; }}
class Diesel : IEngine { public int Power() { return 50; }}
interface IFrame { string Name(); }
class Boxed : IFrame { public string Name() { return "Boxed frame"; }}
class Hat : IFrame { public string Name() { return "Hat frame"; }}
interface TransportFactory {
IEngine CreateEngine();
IFrame CreateChassis();
}
class TrailerCar : TransportFactory {
public IEngine CreateEngine() { return new Diesel(); }
public IFrame CreateChassis() { return new Boxed(); }
}
class PrivateCar : TransportFactory {
public IEngine CreateEngine() { return new Gasoline(); }
public IFrame CreateChassis() { return new Hat(); }
}
Now, I can instantiate private or trailer car.
Some one suggest me changes: engine for trailers cars can by turbo or hybrid. Only for trailers! For private car diesel and gasoline engines still usual diesel engine.
So, if i do changes:
public enum EngineType { Hybrid, Turbo, }
interface TransportFactory
{
IEngine CreateEngine(EngineType t);
IFrame CreateChassis();
}
and i can add classes:
class GasolineHybrid : IEngine
{
public int Power()
{
return 70;
}
}
class GasolineTurbo : IEngine
{
public int Power()
{
return 170;
}
}
class DieselHybrid : IEngine
{
public int Power()
{
return 60;
}
}
class DieselTurbo : IEngine
{
public int Power()
{
return 98;
}
}
it is good, but (!!!) private car nothing to do with it!!!
What kind of design can i use? Old abstraction get incorrect?
Thanks a lot!!!
How about:
class GasolineHybridTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new GasolineHybrid();
}
...
}
class GasolineTurboTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new GasolineTurbo();
}
...
}
class DieselHybridTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new DieselHybrid();
}
...
}
class DieselTurboTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new DieselTurbo();
}
...
}
The idea behind spawning numerous classes is to remove client's ability to do wrong choice. Since you said hybrid and turbo engines do not make sense for private cars, then keeping
IEngine CreateEngine(EngineType t);
will require from private car factory additional efforts to refuse incorrect arguments.
I am not sure did you mean it, but class names suggest that cars are products of factory. In classic relation it will be factory --produce--> product. It is kinky and fun how you put it via generalization, but could be hardly recognizable by others. The beauty of patterns is that once you hear its one word name, then you feel confident about all the internals the implementation could imply.
There is pattern Builder. Would it be more suitable name for your design?
Remember that parameters need not be part of the interface, they can be passed to the constructor of the implementation. So you can still keep your old interface:
interface TransportFactory
{
IEngine CreateEngine();
IFrame CreateChassis();
}
but pass the EngineTypeto the TrailerCar constructor:
class TrailerCar : TransportFactory {
private readonly EngineType engineType;
public TrailerCar(EngineType engineType)
{
this.engineType = engineType;
}
public IEngine CreateEngine()
{
if (engineType == EngineType.Hybrid) return new DieselHybrid();
else return new DieselTurbo();
}
public IFrame CreateChassis() { return new Boxed(); }
}